对于字符数组与字符指针:
1. 以字符串形式出现的,编译器都会为该字符串自动添加一个'\0'作为结束符(ASCII码为0x00),如在代码中写"abc",那么编译器存储的是"abc\0"。
2. 字符串字面值作为字符指针的初始值
"hello"是一个字符串字面值,编译器将其作为const char*处理,与之相关联的内存空间位于内存的只读部分,即允许编译器重用指向等价字符串直接量的引用以优化内存 使用,即使程序中出现了"hello"500次,编译器在内存中也只是创建了一个实例。 例如: char *ptr = “hello”; 等价于 const char *ptr = “hello”;字符串字面值"hello"关联的是只读内存,如果试图修改将出错,例如ptr[1] = ‘a’;运行时程序出错。
3. 字符串字面值作为基于栈的字符数组的初始值
由于基于栈的变量不可能引用其他地方存储的内存,编译器会负责将字符串字面值复制到基于栈的数组内存中。
例如: char stackArray[] = “hello”;
做如下修改: stackArray[1] = ‘a’;是可以的的。
4. 字符数组与字符指针
字符数组的形式如下,会将字符直接量拷贝到栈上:
char str[] = "abc"; // 实际的数据存储: a b c \0
char str[3] = {'a','b','c'}; // 实际的数据存储: a b c,并没有在最后添加终结符
char str[10] = {'a','b','c'}; // 实际的数据存储: a b c \0 \0 \0 \0 \0 \0 \0
字符指针的形式如下:
char *str = “abc”; // 实际的数据存储: a b c \0,str指向首地址
5. 类型的决定
1). 数组的类型是由该数组所存放元素的类型以及数组本身的大小决定的
如char s1[3]和char s2[4],s1的类型就是char[3],s2的类型就是char[4],也就是说尽管s1和s2都是字符数组,但两者的类型却是不同的。
2). 字符串字面值的类型可以理解为相应字符常量数组的类型
如"abcdef"的类型就可以看成是const char[7],也就是说实际的数据存储为"abcdef\0"。
3). 函数参数列表中的数组类型形参,编译器把其解释为普通的指针类型
如对于void func(char sa[100],int ia[20],char *p),则sa的类型为char*,ia的类型为int*,p的类型为char*。
对于sizeof与strlen()
1. sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型。
2. sizeof是单目操作符(与+ - * / 类似),strlen是函数。
3. sizeof可以用类型做参数,strlen只能用char*类型做参数,且必须是以‘\0’结尾的。
4. 数组做sizeof的参数不退化,传递给strlen就退化为指针了。
5. sizeof的结果在编译期间计算出来(不能用来返回动态分配内存的大小),是类型或变量的长度,这就是sizeof(x)可以用来定义数组维数的原因。
strlen的结果要在运行的时候才能计算出来,是用来计算字符串的实际长度,不是类型占内存的大小。
char str[20] = "0123456789"; // str是编译期大小已经固定的数组
int a = strlen(str); // a = 10; strlen()在运行起确定,计算的是实际长度
int b = sizeof(str); // 而b = 20; sizeof()在编译期确定,str的类型是char [20],计算的是占据内存的大小
char *str = "abcd";
int a = sizeof(str); // a = 4; 返回的指针str的大小
int b = sizeof(*str); // b = 1; *str是第一个字符a,大小为1
int c = strlen(*str); // 语句不合法,不能将参数从char转换为const char *
6. sizeof后如果是类型必须加括弧,如果是表达式则可以不加括弧。这是因为sizeof是个操作符不是个函数。
char c;
sizeof c; //变量名可以不加括弧
sizeof(express),其中的express在编译过程中是不会被编译的,而是被替代类型。
例如: int a = 1; sizeof(a = 2);
此时的express为a = 2,在编译过程中被替换为sizeof(int),所以在执行完之后,a仍然是等于1.
对函数使用sizeof,在编译阶段会被替换为函数的返回值的类型取代,不能只写函数名
例如: int f(){return 0;} sizeof(f());的结果为4.
void f(){} sizeof(f());编译过程中会出现错误,替换之后的sizoeof(void)编译无法通过,不能对void类型做sizeof运算。
7. 当作用于一个结构类型或变量, sizeof 返回实际的大小(注意内存对齐);
当作用一静态数组, sizeof 结果等效于将对其元素类型做sizeof操作的结果乘以数组元素个数。
int ia[10] = {0,1,2};
sizeof(ia) = 40;
数组大小sz = sizeof(ia) / size(*ia);
sizeof 操作符不能返回动态分配的数组或外部的数组的尺寸
sizeof、strlen计算字符数组、字符指针结果实例: