赞
踩
这篇文章我很少修改,但是指针却又很牛逼,如文章中有哪些理解的不到位的地方,请留下宝贵的意见
指针是个变量,存放的是地址
#include <stdio.h>
int main()
{
int a = 10; // 在内存中开辟一块空间,存储10
int* p = &a; // 取变量a的地址,可以使用&操作符。
//将a的地址存放在p变量中,故p就是一个存放地址的变量。
return 0;
}
解引用
#include <stdio.h>
int main()
{
int a = 10; // 在内存中开辟一块空间,存储10
int* p = &a; // 取变量a的地址,可以使用&操作符。
// 因为p里面存储的是a的地址,要输出a的值,故要解引用,即加*
printf("%d\n",*p);
return 0;
}
指针的大小在32位平台
是4个字节,在64位平台
是8个字节。
解释:
变量的地址
,而不是存储变量本身
,那么就不关注变量本身是int型,还是char型的了。我们知道 指针的大小在32位平台
是4个字节,在64位平台
是8个字节,那么指针的类型决定了指针向前或者向后走一步有多大(距离)。
举例: int 类型的指针向前走一步是4个字节
的距离,char 类型的指针向前走一步是1个字节
的距离……
总结:
指针的类型决定了,对指针解引用
的时候有多大的权限(能操作几个字节)。 比如char* 的指针解引用就只能访问一个字节,而int* 的指针的解引用就能访问四个字节。
#include <stdio.h> int main() { char c = 'A'; int b = 7; // char型指针 char* pc = &c; // int型指针 int* pb = &b; // 对char型指针 解引用 printf("%c\n",*pc); // A // int型指针 解引用 printf("%d\n",*pb); // 7 return 0; }
void型指针,可以接收任何类型的地址,但是不可以运算和解引用。
#include <stdio.h>
int main() {
int a = 10;
int* p = &a;
char* c = &a;
void* v = &a;
//v++; // error 不可以运算
//*v = 88; // error 不可以解引用
return 0;
}
整型指针--->指向整型地址
字符指针--->指向字符地址
数组指针--->存放数组地址
#include <stdio.h> int main() { int b[10] = { 0 }; int(*pb)[10] = &b; /* 1. &b表示数组首元素地址,那么要存放该数组的地址,就需要指针,所以要声明一个指针,即*pb,但怎么才能是数组指针呢? 答:可以用(*pb)[],表示一个数组指针,那是什么类型的呢? 答:是整形的 */ /*总结来说,数组指针存放数组地址,其实还是一个指针*/ return 0; }
使用案例
#include<stdio.h> int main() { int a[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; int (*p)[4] = a; int i, j; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) { printf("%d ",*(*(p+i)+j)); // 解释说明如下 } printf("\n"); } return 0; }
整型数组--->存放整型
字符数组--->存放字符
指针数组--->存放指针
#include <stdio.h>
int main(){
int a = 16, b = 932, c = 100;
//定义一个指针数组
int *arr[3] = {&a, &b, &c};// 指针数组大小为3,存放3个指针,每个指针指向一个地址
printf("%d, %d, %d\n", *arr[0], *arr[1], *arr[2]); // 指针里面存放的是地址,所以要加*,解引用地址
return 0;
} // 但实际编程环境中,不会这样用指针数组。这里只是便于理解
使用案例
#include <stdio.h> int main() { int a1[] = {1, 1, 1}; int a2[] = {2, 2, 2}; int a3[] = {3, 3, 3}; int i, j; int *pa[] = {a1, a2, a3}; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) printf("%d ", *(pa[i] + j)); // pa[i]:分别找到3个数组首元素地址 printf("\n"); } return 0; } /*int* pa[]--->[]的优先级比*的优先级高,那么[]先和pa结合,成为一个数组。 然后这个数组要存放的数据类型是int*,即要存放的是int形指针。*/
#include <stdio.h>
void test2(int* arr, int len)
{
// 编写代码逻辑
}
int main()
{
int arr[3]={1,2,3};
test2(arr, 3);
return 0;
}
#include <stdio.h>
void test2(int (*arr)[], int r, int c)
{
// 编写代码逻辑
}
int main()
{
int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
test2(arr, 3, 5);
return 0;
}
#include <stdio.h>
void print(int* p, int sz)
{
// 编写代码逻辑
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9 };
int* p = arr;
// 一级指针p
print(p, 10);
return 0;
}
编写形参的技巧
# include<stdio.h> void test(int** ptr) { // 编写代码逻辑 } int main() { int n = 10; int* p = &n; int** pp = &p; // 二级指针pp test(pp); test(&p); return 0; }
#include <stdio.h>
void test(int **arr[]) {
}
int main()
{
int* pa = NULL, * pb = NULL;
int* arr[2] = { pa, pb };
test(arr);
return 0;
}
建议先了解数组指针,不然不好理解函数指针
数组指针:指向数组的地址。其实还是一个指针,只不过是指向了数组的地址。
函数指针:指向函数的地址。其实还是一个指针,只不过是指向了函数的地址。
#include <stdio.h> void test(int x, int y) { printf("%d\n", x + y); } int main() { // &函数名 和 函数名 都是函数的地址 void (*pfun1)(int, int)=test; /* 1. 函数名test是一个地址,那么接收这个函数地址时就需要用指针,所以声明一个指针*pfun1 2. 函数指针 函数指针 这个指针就要指向一个函数,那么怎么才能表达它指向一个函数呢? 答:可以用(*pfun1)(),表示一个指针指向函数,那么指针指向函数的参数是什么类型呢? 答:指针指向函数的参数的类型为int int ,故可以写为(*pfun1)(int, int),那么指针指向函数的返回值是什么类型呢? 答:void,故可以写为void (*pfun1)(int, int) */ /* 1. pfun1表示一个指针,对指针解引用,即*pfun1,拿到test函数地址 2. 拿到test函数地址后不就可以调用函数了嘛 test(3, 4)<=>(*pfun1)(3, 4) */ (*pfun1)(3, 4); //最后再看 pfun1(3, 4); // 上边也可以写成这样的形式。为什么?没有那么多为什么,死记住。(这种写法往往还经常用) return 0; }
用冒泡排序实现一个类似于库函数qsort()的功能
#include <stdio.h> #include <stdlib.h> // qsort() #include <string.h> // strcmp() /*用冒泡排序实现一个类似于库函数qsort()的功能*/ struct Stu { char name[20]; int age; }; /* 第一个参数:是待排序数组首元素地址 第二个参数:是待排序数组的个数 第三个参数:是待排序数组的每个元素的大小-单位是字节 第四个参数:是函数指针,指向自定义比较函数的地址-这个函数指针的两个参数是:代比较元素的地址 */ void _swap(char* p1, char* p2, int width) { int w = 0; //一个一个字节的进行交换 for (w; w < width; w++) { char tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2++; } } // 自定义年龄的比较规则 int cmp_stu_by_name(const void* e1, const void* e2) { // strcmp():字符串比较函数 return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name); } void bubble_sort(void* base, int num, int width, int(*cmp)(void* e1, void* e2)) { int i = 0, j = 0, res = 0; // 比较的趟数 for (i; i < num - 1; i++) { // 每一趟比较的对数 for (j; j < num - 1 - i; j++) { /* 1、(char*)base:表示先把void类型的base指针,先转换为char类型1个字节的指针 2、width:表示字节数 3、j*width:表示j个数组元素的宽度 4、(char*)base + j * width:表示第j个元素的地址 */ res = cmp((char*)base + j * width, (char*)base + (j + 1) * width); if (res > 0) _swap((char*)base + j * width, (char*)base + (j + 1) * width, width); } } } int main() { int i = 0; struct Stu s[] = { {"zhangsan",10}, {"lisi", 30},{"wangwu",20} }; int num = sizeof(s) / sizeof(s[0]); bubble_sort(s, num, sizeof(s[0]), cmp_stu_by_name); for (i; i < num; i++) printf("%s\n", s[i].name); return 0; }
必须先了解函数指针
#include <stdio.h> /*以下四个函数分别为 加减 乘 除*/ int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } int main() { //分别将四个函数的地址,存放在一个函数指针数组*p中 int(*p[4])(int x, int y) = {add, sub, mul, div }; return 0; }
实际运用小栗子
#define _CRT_SECURE_NO_WARNINGS 1 /*实现一个简单的计算器*/ #include <stdio.h> int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { return a / b; } int main() { int x, y; int input = 1; int ret = 0; // p是一个函数指针数组 int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表 while (input) { printf("*************************\n"); printf(" 1:add 2:sub \n"); printf(" 3:mul 4:div \n"); printf("*************************\n"); printf("请选择:"); scanf("%d", &input); if ((input <= 4 && input >= 1)) { printf("输入操作数 数字间用空格隔开:"); scanf("%d %d", &x, &y); ret = (*p[input])(x, y); } else printf("输入有误\n"); printf("ret = %d\n", ret); } return 0; }
必须先了解函数指针数组
#include <stdio.h> void test(const char* str) { printf("%s\n", str); } int main() { // 函数指针pfun void (*pfun)(const char*) = test; // 函数指针的数组pfunArr void (*pfunArr[5])(const char* str); pfunArr[0] = test; //指向函数指针数组pfunArr的指针ppfunArr void (*(*ppfunArr)[10])(const char*) = &pfunArr; return 0; }
回调函数就是一个通过函数指针调用
的函数。如果你把某函数的地址作为参数传递给另一个函数,当这个函数指针被用来调用其所指向的函数时,
我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,
用于对该事件或条件进行响应。
#include <stdio.h> void print(char* str) { printf("%s\n", str); } void test(void (*pfun)(char*)) { pfun("hello world!"); // 触发print } int main() { test(print); // 虽然这里调用了print函数,但是print函数效应,并没有立即发生 return 0; }
野指针成因:
1、指针未初始化
#include <stdio.h>
int main()
{
int* p; // 局部变量指针 p 未初始化,默认指向一个随机地址
*p = 20;
return 0;
}
可以看看指针是怎么初始化的
2、指针越界访问
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i; i <= 11; i++)
{
// 当指针p指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
3、指针指向的空间释放
#include <stdio.h>
int main()
{
char str1[] = "hello";
// 初始化指针
char* st = NULL;
// 使用指针
st = str1;
// 指针解引用
printf("%c",*st); // h
return 0;
}
#include <stdio.h>
int main()
{
// 以下这句话不是把"hello"整个字符串赋值给了*p,而是把首字母的地址赋值给了*p
char* p = "hello";
// 打印第一个元素
printf("%c\n", *p);
// 打印第一个元素的地址
printf("%p\n", p);
// 找到第一个元素的首地址,然后打印出整个字符串
printf("%s\n", p);
return 0;
}
除了字符串可以在找到首字符地址时,接连打印出其它字符,其它类型的不可以
#include <stdio.h>
int main()
{
char* p = "hello"; // "hello"是一个常量字符串
*p = 'x'; // 错误代码
// 找到第一个元素的首地址,然后打印出整个字符串
printf("%s\n", p);
return 0;
}
因为 "hello" 是一个常量字符串,值不能被修改,所以 *p = 'x' 是错误代码。修改为最标准的形式为 const char* p = "hello";
#include <stdio.h> int main() { char str1[] = "hello"; char str2[] = "hello"; char* str3 = "hello"; char* str4 = "hello"; if (str1 == str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if (str3 == str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; }
解释如下:
1、char* str3 = “hello”; 代表常量字符串,不可以被修改,那么就没有必要在内存中,存储2份,1份即可。
2、每声明一个数组,在内存中就会新
申请一个地址,绝不重复。
#include<stdio.h>
int main()
{
int a[] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
int* p = a+5,* q = NULL;
*q = *(p + 5);
printf("%d %d", *p,*q);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> /*求字符串的长度*/ int test(char* s) { char* p = s; while (*++p); // 先进行指针运算即+1,然后对指针解引用 return p - s; // 指针 - 指针 } /*计算字符串占用内存字节的个数*/ int test1(char* s) { char* p = s; while (*p++); // 先对指针解引用,然后p++ // 虽然*p=0 时,while()循环进不去了,但是指针还要在走一步 return (p - s); } int main() { char str[] = "hello world"; printf("%d\n", test(str)); // 11 printf("%d\n", test1(str)); // 12 return 0; }
#include <stdio.h> int main() { // 一维数组 /* * 数组名表示首元素的地址,除了以下这2种情况 * 1. sizeof(数组名):数组名表示整个数组 * 2. &数组名:数组名表示整个数组 */ // 以下为32位平台测试 int a[] = { 1,2,3,4 }; // 16 满足以上条件->sizeof(数组名):数组名表示整个数组 printf("%d\n", sizeof(a)); // 4 这里的数组名a表示首元素的地址,a+0还是首元素地址,地址的大小是4个字节 printf("%d\n", sizeof(a + 0)); // 4 这里的数组名a表示首元素的地址,*a表示首元素,首元素所占的空间为4个字节 printf("%d\n", sizeof(*a)); // 4 这里的数组名a表示首元素的地址,a+1表示第2个元素的地址,地址的大小是4个字节 printf("%d\n", sizeof(a + 1)); // 4 a[1]表示第2个元素,该元素所占的空间为4个字节 printf("%d\n", sizeof(a[1])); // 4 满足以上条件->&数组名:数组名表示整个数组。 // 取出的是整个数组的地址,但是整个数组的地址也是地址,地址的大小是4个字节 printf("%d\n", sizeof(&a)); // 16 &a是数组的地址,数组的地址解引用访问的是整个数组 printf("%d\n", sizeof(*&a)); // 4 &a是数组的地址,&a+1虽然跳过了整个数组的地址,但依旧是地址,地址的大小是4个字节 printf("%d\n", sizeof(&a + 1)); // 4 &a[0]是第一个元素的地址,地址的大小是4个字节 printf("%d\n", sizeof(&a[0])); // 4 &a[0] + 1是第二个元素的地址,地址的大小是4个字节 printf("%d\n", sizeof(&a[0] + 1)); return 0; }
#include <stdio.h> int main() { // 字符数组 /* * 数组名表示首元素的地址,除了以下这2种情况 * 1. sizeof(数组名):数组名表示整个数组 * 2. &数组名:数组名表示整个数组 */ // 以下为32位平台测试 char arr[] = { 'a','b','c','d','e','f' }; // 6 满足以上条件->sizeof(数组名):数组名表示整个数组 printf("%d\n", sizeof(arr)); // 4 这里的arr,表示数组首元素的地址,arr+0还是首元素的地址,地址的大小是4个字节 // 在这里你可能有疑问了?不是char型地址吗?不应该是1个字节吗,怎么会是4个字节?请看上面专题 c 语言 指针类型的意义 然后类比 printf("%d\n", sizeof(arr + 0)); // 1 arr是首元素的地址,*arr是首元素,首元素所占的空间是1个字节 printf("%d\n", sizeof(*arr)); // 1 printf("%d\n", sizeof(arr[1])); // 4 满足以上条件->&数组名:数组名表示整个数组。但是数组地址也是个地址,地址的大小是4个字节 printf("%d\n", sizeof(&arr)); // 4 满足以上条件->&数组名:数组名表示整个数组。&arr + 1是跳过了整个数组后的地址,只要是地址,地址的大小就是4个字节 printf("%d\n", sizeof(&arr + 1)); // 4 &arr[0]表示第一元素的地址,&arr[0] + 1表示第二个元素的地址,地址的大小是4个字节 printf("%d\n", sizeof(&arr[0] + 1)); // 随机值 因为数组末尾没有结束标志\0,所以'\0'位置放了一个随机值。这里的arr表示首元素的地址 printf("%d\n", strlen(arr)); // 随机值 因为数组末尾没有结束标志\0,所以'\0'位置放了一个随机值。这里的arr表示首元素的地址,arr + 0还是首元素的地址 printf("%d\n", strlen(arr + 0)); // 报错 这里的arr表示首元素的地址,*arr表示解引用,找到了首元素'a','a'对应ascll码表十进制的值为97, // 那么strlen函数就把97当作起始地址值,开始从这里向后面数数。那么自然而然就会出现错误,即非法访问内存了 //printf("%d\n", strlen(*arr)); // 报错 理由同上 //printf("%d\n", strlen(arr[1])); // 随机值 满足以上条件->& 数组名:数组名表示整个数组。因为数组末尾没有结束标志\0,所以'\0'位置放了一个随机值。 printf("%d\n", strlen(&arr)); // 随机值 满足以上条件->& 数组名:数组名表示整个数组。&arr + 1是跳过了整个数组后的地址。 printf("%d\n", strlen(&arr + 1)); // 随机值 &arr[0]表示第一元素的地址,&arr[0] + 1表示第二个元素的地址,因为数组末尾没有结束标志\0,所以'\0'位置放了一个随机值。 printf("%d\n", strlen(&arr[0] + 1)); return 0; }
#include <stdio.h> int main() { /* * 数组名表示首元素的地址,除了以下这2种情况 * 1. sizeof(数组名):数组名表示整个数组 * 2. &数组名:数组名表示整个数组 */ // 以下为32位平台测试 char arr[] = "abcdef"; // 7 满足以上条件->sizeof(数组名):数组名表示整个数组。因为字符串末尾隐藏了\0,所以整个数组所占的空间是7个字节 printf("%d\n", sizeof(arr)); // 4 这里的arr是首元素的地址,arr+0还是首元素的地址。地址的大小是4个字节 printf("%d\n", sizeof(arr + 0)); // 1 这里的arr是首元素的地址,*arr表示首元素。首元素所占的空间是1个字节 printf("%d\n", sizeof(*arr)); // 1 第2个元素所占的空间是1个字节 printf("%d\n", sizeof(arr[1])); // 4 满足以上条件->&数组名:数组名表示整个数组。但是数组的地址也是地址,地址的大小是4个字节 printf("%d\n", sizeof(&arr)); // 4 满足以上条件->& 数组名:数组名表示整个数组。&arr + 1是跳过整个数组后的地址,但也是地址。地址的大小是4个字节 printf("%d\n", sizeof(&arr + 1)); // &arr[0]表示首元素的地址,&arr[0] + 1是第二个元素的地址。地址的大小是4个字节 printf("%d\n", sizeof(&arr[0] + 1)); // 6 这里的arr是首元素的地址,strlen函数会从这个地址,向后面数数,直到遇到\0, printf("%d\n", strlen(arr)); // 6 这里的arr是首元素的地址,arr + 0 还是首元素的地址,strlen函数会从这个地址,向后面数数,直到遇到\0, printf("%d\n", strlen(arr + 0)); // 报错 这里的arr表示首元素的地址,*arr表示解引用,找到了首元素'a','a'对应ascll码表十进制的值为97, // 那么strlen函数就把97当作起始地址值,开始准备从这里向后面数数。那么自然而然就会出现错误,即非法访问内存了 //printf("%d\n", strlen(*arr)); // 报错 理由同上 //printf("%d\n", strlen(arr[1])); // 6 满足以上条件->& 数组名:数组名表示整个数组。strlen函数会从起始地址开始向后数数,直到遇到\0 printf("%d\n", strlen(&arr)); // 随机值 满足以上条件->& 数组名:数组名表示整个数组。 // &arr + 1是跳过整个数组后的地址,但也是地址。 // 地址的大小是4个字节,可是我们求的不是地址大小,而是元素的个数,strlen函数会从跳过整个数组后的地址开始向后数数 // 然而这个地址处和后面没有元素,所以会出现随机值 printf("%d\n", strlen(&arr + 1)); // 5 &arr[0]首元素的地址,&arr[0] + 1 第2个元素的地址。strlen函数会从这个地址开始向后面数数,直到遇到\0 printf("%d\n", strlen(&arr[0] + 1)); return 0; }
#include <stdio.h> int main() { // 以下为32位平台测试 char* p = "abcdef"; // 4 p是一个指针变量, sizeof(p)计算指针变量的大小 // 4 也可以这里理解,p指向首元素的地址(注意用词:指向),不管是什么类型的地址,地址的大小都是4个字节 printf("%d\n", sizeof(p)); // 4 p指向首元素的地址,p+1指向第二个字符的地址,不管是什么类型的地址,地址的大小都是4个字节 printf("%d\n", sizeof(p + 1)); // 1 p指向首元素的地址,*p表示解引用,找到字符'a', 字符'a'所占的空间是一个字节 printf("%d\n", sizeof(*p)); // 1 p[0] == *(p+0) p指向首元素地址,p+0还是指向首元素的地址,*(p+0)表示解引用,找到字符'a', 字符'a'所占的空间是一个字节 printf("%d\n", sizeof(p[0])); // 4 含义如下图 &p:表示地址,不管是什么类型的地址,地址的大小都是4个字节 printf("%d\n", sizeof(&p)); // 4 含义如下图 &p+1:表示地址,不管是什么类型的地址,地址的大小都是4个字节 printf("%d\n", sizeof(&p + 1)); // 4 含义如下图 p[0]表示字符'a',&p[0]表示找到字符'a'的地址,&p[0]+1表示找到字符'b'的地址,不管是什么类型的地址,地址的大小都是4个字节 printf("%d\n", sizeof(&p[0] + 1)); // 6 p指向首元素的地址,strlen函数从这个地址处,向后面数数,直到遇到\0 printf("%d\n", strlen(p)); // 5 p指向首元素的地址,p+1指向第二个字符的地址,strlen函数从这个地址处,向后面数数,直到遇到\0 printf("%d\n", strlen(p + 1)); // 报错 p指向首元素的地址,*p表示解引用,找到了首元素'a','a'对应ascll码表十进制的值为97, // 那么strlen函数就把97当作起始地址值,开始准备从这里向后面数数。那么自然而然就会出现错误,即非法访问内存了 //printf("%d\n", strlen(*p)); // 报错 理由同上 //printf("%d\n", strlen(p[0])); // 随机值 &p表示起始地址,strlen函数,会从该处,开始向后面数数,但因为p里面存放的是随机地址,这个随机地址中什么时候出现\0不确定,所以才为随机值 printf("%d\n", strlen(&p)); // 随机值 理由同上 printf("%d\n", strlen(&p + 1)); // 5 p[0]表示字符'a',&p[0]表示找到字符'a'的地址,&p[0]+1表示找到字符'b'的地址,strlen函数从此处开始向后数数,直到遇到\0 printf("%d\n", strlen(&p[0] + 1)); return 0; }
#include <stdio.h> int main() { // 二维数组 int a[3][4] = { 0 }; // 48 sizeof(数组名):数组名表示整个数组 printf("%d\n", sizeof(a)); // 4 printf("%d\n", sizeof(a[0][0])); // 16 a[0]相当于第一行一维数组的数组名,sizeof(a[0])计算的是第一行的大小 printf("%d\n", sizeof(a[0])); // 4 a[0]是第一行的数组名,数组名此时是第一行首元素的地址,a[0]+1是第一行第二个元素的地址,地址的大小是4个字节 printf("%d\n", sizeof(a[0] + 1)); // 4 *(a[0] + 1))第一行第二个元素的所占空间为4个字节 printf("%d\n", sizeof(*(a[0] + 1))); // 4 a是二维数组的数组名,没有sizeof(a),也没有&a,所以a是首元素地址, // 二维数组的首元素是他的第一行,a就是第一行元素的地址,a+1就是第二行首元素的地址 printf("%d\n", sizeof(a + 1)); // 16 a+1就是第二行首元素的地址,*(a[0] + 1))是第二行元素的大小 printf("%d\n", sizeof(*(a + 1))); // &a[0] + 1第二行的地址 printf("%d\n", sizeof(&a[0] + 1)); // *(&a[0] + 1))第二行的大小 printf("%d\n", sizeof(*(&a[0] + 1))); // 16 a是首元素的地址,第一行的地址。*a就是第一行,sizeof(*a)计算第一行的大小 printf("%d\n", sizeof(*a)); // 16 sizeof函数计算的是类型的大小,即计算的是存放了4个整型数的一维数组的大小,与该数组是否越界无关。 printf("%d\n", sizeof(a[3])); return 0; } /* int a[2][3] = { 1, 2, 3, 4, 5 ,6 }; printf("%p\n",&a[0][1]); printf("%p\n",a[0]+1); printf("%p\n", &a[1][1]); printf("%p\n", a[1] + 1); */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。