strlen sizeof详尽分析

来源:互联网 发布:flyme 彻底清除数据 编辑:程序博客网 时间:2024/05/06 11:22

1   char *a="qwert";

cout<<a+2<<endl;

输出  ert   如果cout后面带的是地址,那么输出从这个地址开始的字符串!

实战例子)

1)

char *aa = new char[22];
    cout << sizeof(aa) << endl;//结果 4 ===》aa是指针
    char a1[6] = { '1', '2', '3', '4', '5', '6' };
    char a2[] = { '1', '2', '3', '4', '5', '6' };
    cout << sizeof(a1) << endl;//结果 6 ===》非常量字符串,只有6,不是7,不包含\0
    cout << sizeof(a2) << endl;//结果 6 ===》非常量字符串,只有6,不是7,不包含\0
    cout << strlen(a1) << endl;//结果 19 ===》函数strlen读到\0才会结束,a1字符串没有\0,所以结果无法预计
    cout << strlen(a2) << endl;//结果 35 ===》函数strlen读到\0才会结束,a2字符串没有\0,所以结果无法预计

    char str3[] = "abcse\0fgkij";
    cout << "strlen(str3)=" << strlen(str3) << endl; //结果 5 ===》 str3的'\0'会被解释为结束符

    char *s1 = "zclzcl";
    char s2[] = "cxlcxl";
    cout << strlen(&s1[4]) << endl;//结果 2 ===》从字符串倒数开始计时读整个字符串,直到遇到\0常量字符串的标示符停止
    cout << sizeof(s1) << endl;//结果 4 ===》s1是指向字符串常量的字符指针
    cout << sizeof(s2) << endl;//结果 7 ===》常量字符串包含最后的\0标示符
    cout << strlen(s1) << endl;//结果 6 ===》函数strlen读到\0才会结束
    cout << strlen(s2) << endl;//结果 6 ===》函数strlen读到\0才会结束
    //sizeof只有在输入为char *s="zcl"或者char *s=new char时,s为sizeof参数就会作为指针,32位系统就是4个字节。

1) 看运算符的优先级

int *p[5]; []优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。 是指针数组,  有 5 个成员,每个成员都是一个指针,共有5 个指针
int (*p)[5];  小括号优先,所以 是 1个指针,用来指向 有5个元素的数组。
--------
一般来说
 int (*p)[n];  是数组指针(也称行指针)
()优先级高,说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
所以数组指针也称指向一维数组的指针,亦称行指针。
----
int *p[n]; 指针数组
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1是错误的,这样赋值也是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。。

2)

void f(char*x){
    x++;
    *x = 'a';
}
int main(int argc, char**argv){
    char str[sizeof("hello")];
    strcpy(str, "hello");
    f(str);
    std::cout << str;//hallo
    system("pause");
    return EXIT_SUCCESS;
}

void f() 函数输入的str 数组作为函数的输入变为指针,指向“hello”的第一个字符h, 因为f函数输入的是指针,那么x++,也就是str++之后,修改了“hello”第二个数组地址的字符为a,所以将cout<<str输出时输出整个修改后的字符串为hallo。

3)

char arr[10]="hello";

cout<<strlen(arr)<<endl;//5  只关心实际存储内容,到\0停止

cout<<sizeof(arr)<<endl;//10 关心数组的分配的空间大小和类型

char *parr=new char[10];

cout<<strlen(parr)<<endl;//14

cout<<sizeof(parr)<<endl;//4  parr是一个指针

cout<<sizeof(*parr)<<endl;//1

程序定义了一个字符指针parr ,它指向一个分配了10个字节的空间的字符数组,由于没有进行初始化,根据strlen原理,它无法确定字符串的终止位置,所以该值为一个随机值,本例中输出14,;parr为一个指针,sizeof自然输出4个字节。*parr为指向字符串第一个字符的空间大小,sizeof在编译时既可确定为1,即char型所占空间大小。

        char cvar[20]="enock";
        int  ivar[20]={1,2,3};

        char *cp=new char[5];
        printf("%d\n",sizeof(cvar));//20
        printf("%d\n",sizeof(ivar));//80

        printf("%d\n",sizeof(cp));//4 ,cp是指针变量

(1)需要注意的是参数传递时,静态数组参数会弱化为指针,因为不可能在调用栈上去分配一个数组。所以

         void fun(char cvar[]){

                printf("%d\n",sizeof(cvar));

          }

         fun(cvar);//4  32位机指针变量占4个字节

(2)字面值字符串是const char[]类型,即静态数组类型

          printf("%d\n",sizeof("enock"));//6,注意结尾'\0'

(3)sizeof(结构体对象),需要注意字节对齐,这跟编译器相关。

(4)在使用数组时,大多数情况下数组会自动转换为指向第一个元素的指针,不将数组转换为指针的情况有:数组用作取地址(&)操作符的操作数或sizeof的操作数,或用数组对数组的引用进行初始化时,不会将数组转换为指针,如下:(注意 1、这里是sizeof,不是strlen;  2、这里输入函数的数组用*a和a[]都是可以的!!!)

void fun1(int a[]){
    std::cout << sizeof(a) << std::endl;
}
void fun2(int(&a)[5]){//数组的引用  
    std::cout << sizeof(a) << std::endl;
}
int main(int argc, char** argv){
    std::cout << "sizeof int=" << sizeof(int) << std::endl; //4
    int a[5];
    std::cout << sizeof(a) << std::endl;//20
    fun1(a);//4
    fun2(a);//20
    int(*p)[5] = &a;//p是5维数组的指针  p是指针,*p自然就是数组啦
    std::cout << sizeof(p) << std::endl;//4
    std::cout << sizeof(*p) << std::endl;//20

    system("pause");

    return 0;
}


2) int *a[2][3]  共占用48个字节

第二题选D,不解释,2*3*sizeof(int*)=48(64位机器上是8字节一个指针)





经验)

1 strlen只能用char*作为参数,而且必须是以“\0”结尾的,例如char a[5]="hello"就会出错,没有空间存放'\0'。

2 http://blog.csdn.net/xhu_eternalcc/article/details/22588133

3     char a[6] = "123456";//error "123456" char型实际上有7个字节,包括最后的'\0'
    char a1[6] = {'1','2','3','4','5','6'}; //正确  不包含结束符

4 sizeof只有在输入为char *s="zcl"或者char *s=new char时,s为sizeof参数就会作为指针,32位系统就是4个字节。

5   剑指offer T48

void swap(char *a, char *b)
{
    char tmp = *a;
    *a = *b;
    *b = tmp;
}

void main()
{
    char *p = "hello";
    swap(p, p + 2);//因为传入swap函数的p是一个存于常量区的字符串的指针copy,在swap函数内部,通过这个指针copy来解引用修改在常量区字符串“hello”的值当然是不可能的,自然会报错!!可以将p写成数组形式就可以,比如char p[]="hello", 因为此时字符串存在栈区,通过指针p就可以修改了!!这也是字符串指针和字符串本质区别char *p和char p[]!!

1 char pData[] = "i am a student.";                      char *pData = "i am a student.";

后者字符串如果为指针型表示,则此字符串为const类型,不可以更改此字符串内容,但是前者数组的形式可以。

比如char *func(char *pData)   此函数的指针输入参数只能选择前者char pData[] = "i am a student.";   选择后者作为参数会出错!!

所以可以有char str[]={'a','b','c'}; 但不可以有 char *str={'a','b','c'}//没有这种写法,不符合语法形式。{}代表数组,但是char *str只能代表常量字符串!!

但是这样是可以的char *a2[] = { "abc","cde" } 代表a2是一个数组,里面每一项是一个常量字符串!!!




原创粉丝点击