目录
[1. 与一维数组相关](#1. 与一维数组相关)
[2. 与字符数组相关](#2. 与字符数组相关)
[2.1 逐字符初始化的字符数组与sizeof](#2.1 逐字符初始化的字符数组与sizeof)
[2.2 逐字符初始化的字符数组与strlen](#2.2 逐字符初始化的字符数组与strlen)
[2.3 字符串初始化的字符数组与sizeof](#2.3 字符串初始化的字符数组与sizeof)
[2.4 字符串初始化的字符数组与strlen](#2.4 字符串初始化的字符数组与strlen)
[3. 与常量字符串相关](#3. 与常量字符串相关)
[3.1 常量字符串与sizeof](#3.1 常量字符串与sizeof)
[3.2 常量字符串与strlen](#3.2 常量字符串与strlen)
[4. 与二维数组相关](#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. 与一维数组相关
cpp
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
cpp
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
cpp
#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
cpp
int main() {
char arr[] = "abcdef";
// a b c d e f \0
printf("%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
cpp
#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: 6B
printf("%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: 6B
printf("%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: 5B
return 0;
}
运行结果如下:
3. 与常量字符串相关
3.1 常量字符串与sizeof
cpp
#include<stdio.h>
int main() {
char* p = "abcdef";
// 隐含一个\0: a b c d e f \0
printf("%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
cpp
#include<string.h>
#include<stdio.h>
int main() {
char* p = "abcdef";
// 隐含一个\0: a b c d e f \0
printf("%d\n", strlen(p));
// p=&('a'),'a'->\0: 6
printf("%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: 5
return 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表示跳过一行一维数组后的第二行一维数组的数组地址;
cpp
#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=16
printf("%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位平台):