目录
1. 与一维数组相关
2. 与字符数组相关
2.1 逐字符初始化的字符数组与sizeof
2.2 逐字符初始化的字符数组与strlen
2.3 字符串初始化的字符数组与sizeof
2.4 字符串初始化的字符数组与strlen
3. 与常量字符串相关
3.1 常量字符串与sizeof
3.2 常量字符串与strlen
4. 与二维数组相关
关于sizeof与strlen,相关文章如下:
【C语言】_sizeof与strlen-CSDN博客https://blog.csdn.net/m0_63299495/article/details/145082378关于数组与指针,相关文章如下:
【C语言】_指针与数组-CSDN博客https://blog.csdn.net/m0_63299495/article/details/144947245由于指针相关计算易错易混淆,本文整理指针与数组的相关计算用例。
1. 与一维数组相关
int main() {int a[] = { 1,2,3,4 };printf("%d\n", sizeof(a));// sizeof(数组名):表示整个数组大小=4*4=16;printf("%d\n", sizeof(a + 0));// 数组名a=数组首元素地址(int*类型),a+0仍为首元素地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*a));// 数组名a=数组首元素地址(int*类型),*a为首元素(int类型),sizeof(int型变量)=4;printf("%d\n", sizeof(a + 1));// 数组名a=数组首元素地址(int*类型),a+1表示跳过1个int型数据后的地址,即第二个元素的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(a[1]));// a[1]即第二个元素,sizeof(int型变量)=4;printf("%d\n", sizeof(&a));// &a=整个数组地址(int*类型),sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*&a));// &a=整个数组地址,*&a表示数组所有元素,sizeof(4个int型数据)=4*4=16;// *与&抵消,sizeof(*&a)=sizeof(a),表示整个数组的大小=4*4=16;printf("%d\n", sizeof(&a + 1));// &a=整个数组地址,&a+1表示跳过整个数组后的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&a[0]));// &a[0]=数组首元素的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&a[0] + 1));// &a[0]=数组首元素的地址(int*型),&a[0]+1表示跳过1个int型数据后的地址,sizeof(地址)=4或8(与平台有关);return 0;
}
运行结果如下:
x86(32位平台):
x64(64位平台):
2. 与字符数组相关
2.1 逐字符初始化的字符数组与sizeof
int main() {char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr));// sizeof(数组名)表示整个数组的大小=6*1=6;printf("%d\n", sizeof(arr + 0));// 数组名arr表示数组首元素地址(char*类型),sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*arr));// 数组名arr表示数组首元素地址,*arr表示数组首元素(char类型),sizeof(char型变量)=1;printf("%d\n", sizeof(arr[1]));// arr[1]表示数组下标为1的元素(char型),sizeof(char型变量)=1;printf("%d\n", sizeof(&arr));// &数组名表示整个数组的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&arr + 1));// &数组名表示整个数组的地址,&arr+1表示跳过整个数组后的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&arr[0] + 1));// &arr[0]表示数组首元素的地址,&arr[0]+1表示跳过一个数组元素后的地址,sizeof(地址)=4或8(与平台有关);return 0;
}
运行结果如下:
x86(32位平台):
x64(64位平台):
2.2 逐字符初始化的字符数组与strlen
#include<string.h>int main() {char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));// arr表示首元素地址,字符数组中不含\0,\0位置未知,长度为 > 6的随机值printf("%d\n", strlen(arr + 0));// arr表示首元素地址,arr+0仍为首元素地址,字符数组中不含\0,\0位置未知,长度为 > 6的随机值// printf("%s\n", strlen(*arr));// arr表示数组首元素地址,*arr表示数组首元素字符a(ASCII码值为97),streln要求参数为起始检索地址,97地址为野指针,程序报错// printf("%d\n", strlen(arr[1]));// arr[1]表示数组下标为1的元素字符b(ASCII码值为98),streln要求参数为起始检索地址,98地址为野指针,程序报错printf("%d\n", strlen(&arr));// &arr表示整个数组的地址,在数值上等于数组首元素的地址,字符数组中不含\0,\0位置未知,长度为 > 6的随机值printf("%d\n", strlen(&arr + 1));// &arr表示整个数组的地址,&arr+1表示跳过整个数组(6字节)后的地址,相较于起始地址,该结果为起始地址对应产生随机值减小6后的随机值printf("%d\n", strlen(&arr[0] + 1));// &arr[0]表示数组首元素的地址,&arr[0]+1表示跳过1个元素(1字节)后的地址,相较于起始地址,该结果为起始地址对应产生随机值减小1后的随机值return 0;
}
运行结果如下:
2.3 字符串初始化的字符数组与sizeof
int main() {char arr[] = "abcdef";// a b c d e f \0printf("%d\n", sizeof(arr));// sizeof(数组名)表示整个数组的大小=7;printf("%d\n", sizeof(arr + 0));// arr=&arr[0],arr+0=arr=&arr[0],sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*arr));// arr=&arr[0],*arr=arr[0]='a'(char型),sizeof(char型变量)=1;printf("%d\n", sizeof(arr[1]));// arr[1]='b'(char型),sizeof(char型变量)=1;printf("%d\n", sizeof(&arr));// &arr表示整个数组的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&arr + 1));// &arr表示整个数组的地址,&arr+1表示跳过整个数组(7B)后的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&arr[0] + 1));// &arr[0]表示数组首元素的地址,&arr[0]+1表示跳过1个元素(1B)后的地址,sizeof(地址)=4或8(与平台有关);return 0;
}
运行结果如下:
x86(32位平台):
x64(64位平台):
2.4 字符串初始化的字符数组与strlen
#include<string.h>
#include<stdio.h>
int main() {char arr[] = "abcdef";// a b c d e f \0 共7个元素printf("%d\n", strlen(arr));// arr=&arr[0]=&('a'),'a'->\0: 6Bprintf("%d\n", strlen(arr + 0));// arr=arr+0=&arr[0]=&('a'),'a'->\0: 6B// printf("%d\n", strlen(*arr));// arr=&arr[0],*arr=arr[0]='a'=97,strlen将97解析为地址,判定为野指针,程序报错// printf("%d\n", strlen(arr[1]));// arr[1]='b'=98, strlen将98解析为地址,判定为野指针,程序报错;printf("%d\n", strlen(&arr));// &arr数值上=&arr[0]=&('a'),'a'->\0: 6Bprintf("%d\n", strlen(&arr + 1));// &arr+1表示跳过整个数组(7B)后的地址,\0位置未知,为随机值printf("%d\n", strlen(&arr[0] + 1));// &arr[0]+1表示跳过首元素(1B)后的地址=&arr[1]=&('b'),'b'->\0: 5Breturn 0;
}
运行结果如下:
3. 与常量字符串相关
3.1 常量字符串与sizeof
#include<stdio.h>
int main() {char* p = "abcdef";// 隐含一个\0: a b c d e f \0printf("%d\n", sizeof(p));// p=&('a')(char*类型),sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(p + 1));// p+1表示跳过一个元素(1B)后的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*p));// p=&('a'),*p='a'(char类型),sizeof(char型变量)=1;printf("%d\n", sizeof(p[0]));// p[0]='a'(char类型),sizeof(char型变量)=1;printf("%d\n", sizeof(&p));// p=&('a')(char*类型),&p为二级指针(char**类型),sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&p + 1));// &p为二级指针(char**类型),&p+1表示跳过一个char*类型的元素(4或8B)后的地址,sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(&p[0] + 1));// p[0]='a'(char类型),&p[0]=&('a'),&p[0]+1表示跳过1个元素(1B)后的地址,sizeof(地址)=4或8(与平台有关);return 0;
}
运行结果如下:
x86(32位平台):
x64(64位平台):
3.2 常量字符串与strlen
#include<string.h>
#include<stdio.h>
int main() {char* p = "abcdef";// 隐含一个\0: a b c d e f \0printf("%d\n", strlen(p));// p=&('a'),'a'->\0: 6printf("%d\n", strlen(p + 1));// p=&('a'),p+1=&('b'),'b'->\0: 5// printf("%d\n", strlen(*p));// p=&('a'),*p='a'=97,strlen将97解析为地址,判定为野指针,程序报错// printf("%d\n", strlen(p[0]));// p[0]='a'=97,strlen将97解析为地址,判定为野指针,程序报错printf("%d\n", strlen(&p));// p=&('a'),&p为二级指针(char**类型),&p未知,自&p起\0位置未知,输出随机值printf("%d\n", strlen(&p + 1));// p=&('a')(char*类型),&p为二级指针(char**类型),&p未知,&p+1表示跳过一个char*(4B)后的地址,输出随机值printf("%d\n", strlen(&p[0] + 1));// &p[0]=&('a'),&p[0]+1表示跳过1个char(1B)后的地址=&p[1]=&('b'),'b'->\0: 5return 0;
}
运行结果如下:(以x86为例,地址4B)
4. 与二维数组相关
关于二维数组,相关文章如下:
【C语言】_指针数组和数组指针-CSDN博客https://blog.csdn.net/m0_63299495/article/details/145033052关于二维数组arr[ m ] [ n ]的理解:
(1)数组名arr:表示二维数组第一行的一维数组的地址;
(2)arr[ i ] (0 ≤ i ≤ m):即二维数组第 i 行的一维数组的数组名;
关于特殊情况的判定:
(1)当数组名单独放至sizeof内部时,即sizeof (数组名)时,数组名不可解析为数组首元素地址,此时sizeof计算的是整个数组的大小;
对于二维数组,需注意arr [ i ] 的含义,sizeof(arr[i])表示数组第i行一维数组的n个元素的大小;
(2)当&数组名时,数组名不可解析为数组首元素地址,此时&数组名取到的是整个数组的地址。
在数值上确实等于数组首元素的地址,但当其进行+-整数的运算时,则会出现不同;
对于二维数组,需注意arr [ i ] 的含义,&arr[ i ]+1表示跳过一行一维数组后的第二行一维数组的数组地址;
#include<string.h>
#include<stdio.h>
int main() {int a[3][4] = { 0 };printf("%d\n", sizeof(a));// sizeof(数组名)表示整个数组的大小=3*4*4=48;printf("%d\n", sizeof(a[0][0]));// sizeof(int型数据)=4;printf("%d\n", sizeof(a[0]));// a[0]表示二维数组第1行一维数组的数组名,sizeof(数组名)=整个一维数组的大小=4*4=16;printf("%d\n", sizeof(a[0] + 1));// a[0]表示二维数组第1行一维数组的数组名,由于a[0]并未单独放至sizeof内部,故a[0]=&a[0][0],// a[0]+1=&a[0][0]+1=&a[0][1], sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*(a[0] + 1)));// a[0]+1=&a[0][0]+1=&a[0][1], *(a[0] + 1)=*(&a[0][1])=a[0][1],sizeof(int型数据)=4;printf("%d\n", sizeof(a + 1));// a=&a[0],a+1=&a[0]+1=&a[1],即二维数组第2行的一维数组的数组名,// 由于a作为数组名并未单独放至sizeof内部,故a+1=&a[0]+1=&a[1](数组指针类型),sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*(a + 1)));// a+1=&a[1]+1=&a[1],*(a+1)=*(&a[1])=&a[1],表示数组第2行的一维数组的大小=4*4=16;printf("%d\n", sizeof(&a[0] + 1));// a[0]表示数组第1行一维数组的数组名,&数组名表示整个数组的地址,&a[0]表示第1行一维数组的数组地址,// &a[0]+1表示跳过一行数组后的数组地址,即第2行一维数组的数组地址,&a[0]+1=&a[1],sizeof(地址)=4或8(与平台有关);printf("%d\n", sizeof(*(&a[0] + 1)));// &a[0]+1=&a[1],*(&a[0] + 1))=*(&a[1])=a[1],即表示数组第2行一维数组的4个元素,sizeof(a[1])=4*4=16printf("%d\n", sizeof(*a));// a=&a[0],*a=*(&a[0])=a[0],sizeof(a[0])=4*4=16;printf("%d\n", sizeof(a[3]));// a[3]表示数组第3行一维数组的数组名,数组名单独放至sizeof内部,表示整个一维数组的大小=4*4=16;return 0;
}
运行结果如下:
x86(32位平台):
x64(64位平台):