云计算百科
云计算领域专业知识百科平台

C语言初学者笔记【指针相关试题】

文章目录

  • 前言
  • 一、pandas是什么?
    • 1. sizeof 和 strlen 对比
  • 二、 数组和指针试题解析
    • 1.一维数组
    • 2.字符数组
  • 三、指针运算试题解析
    • 1.数组指针偏移
    • 2. 结构体指针运算(X86)
    • 3.逗号表达式陷阱
    • 4.数组指针类型不匹配(X86)
    • 5.二维数组地址偏移
    • 6.指针数组
    • 7.三级指针与字符串
  • 关键总结

前言

指针学习的内容非常复杂,这里通过sizeof和strlen为引子,解析部分指针相关试题,主要涉及指针定位的偏移,多级指针变量解析


一、pandas是什么?

1. sizeof 和 strlen 对比

特性sizeofstrlen
本质 编译时运算符 库函数(需 <string.h>)
功能 计算操作数占内存大小(字节) 统计 \\0 前的字符个数
关注内容 内存空间大小(不关心数据内容) 依赖 \\0 结束符(无 \\0 会越界访问)
操作数类型 变量、数据类型、数组、指针等 必须是字符串地址(const char*)
示例 sizeof(int) = 4(32位系统) strlen("abc") = 3

关键区别:

  • 数组名在 sizeof 中的意义:
    • sizeof(数组名):计算整个数组大小(如 int a[4] → 16 字节)。
    • &数组名:取整个数组的地址(类型为数组指针)。
    • 其他情况(如 a+0):数组名退化为首元素地址。

二、 数组和指针试题解析

1.一维数组

int a[] = {1,2,3,4};
printf("%d\\n", sizeof(a)); // 16 → 整个数组大小 (4个int)
printf("%d\\n", sizeof(a+0)); // 4/8 → 首元素地址(指针大小)
printf("%d\\n", sizeof(*a)); // 4 → a[0] (int类型)
printf("%d\\n", sizeof(&a)); // 4/8 → 数组指针(地址大小)
printf("%d\\n", sizeof(&a[0])); // 4/8 → 元素地址

2.字符数组

代码1(无 \\0 初始化):

char arr[] = {'a','b','c','d','e','f'};
printf("%d\\n", sizeof(arr)); // 6 → 整个数组大小
printf("%d\\n", strlen(arr)); // 随机值 → 无 `\\0` 导致越界查找

代码2(字符串初始化):

char arr[] = "abcdef"; // 隐含 '\\0'
printf("%d\\n", sizeof(arr)); // 7 → 包含 '\\0'
printf("%d\\n", strlen(arr)); // 6 → '\\0' 前字符数

代码3(指针指向字符串):

char *p = "abcdef";
printf("%d\\n", sizeof(p)); // 4/8 → 指针大小
printf("%d\\n", strlen(p)); // 6 → 字符串长度


三、指针运算试题解析

1.数组指针偏移

int a[5] = {1,2,3,4,5};
int *ptr = (int *)(&a + 1); // &a+1 跳过整个数组
printf("%d,%d", *(a+1), *(ptr1)); // 输出:2,5

图解:

a: [1][2][3][4][5] | 越界位置
↑ ↑ ↑
a a+1 ptr → ptr-1指向5


2. 结构体指针运算(X86)

struct Test *p = (struct Test*)0x100000;
printf("%p\\n", p + 0x1); // 0x100014 → 跳过20字节结构体
printf("%p\\n", (unsigned long)p + 0x1); // 0x100001 → 数值+1
printf("%p\\n", (unsigned int*)p + 0x1); // 0x100004 → 跳过4字节(int)


3.逗号表达式陷阱

int a[3][2] = { (0,1), (2,3), (4,5) }; // 逗号表达式→{1,3,5}
int *p = a[0];
printf("%d", p[0]); // 输出:1

实际初始化:

a[0][0]=1, a[0][1]=3, a[1][0]=5, 其余为0


4.数组指针类型不匹配(X86)

int a[5][5];
int(*p)[4] = a; // p的步长=4个int(但a每行5个int)
printf("%p,%d\\n", &p[4][2] &a[4][2], &p[4][2] &a[4][2]);
// 输出:0xfffffffc, -4(地址差为-4个int)

图解:

p[4][2] → 指向第18个元素(a[3][3])
a[4][2] → 指向第22个元素(下标4*5+2=22)
差值 = 18 – 22 = -4


5.二维数组地址偏移

int aa[2][5] = {1,2,3,4,5,6,7,8,9,10};
int *ptr1 = (int *)(&aa + 1); // 跳过整个二维数组
int *ptr2 = (int *)(*(aa + 1)); // 指向第二行首元素
printf("%d,%d", *(ptr11), *(ptr21)); // 输出:10,5


6.指针数组

char *a[] = {"work","at","alibaba"};
char **pa = a;
pa++; // 指向a[1]("at")
printf("%s\\n", *pa); // 输出:"at"


7.三级指针与字符串

char *c[] = {"ENTER","NEW","POINT","FIRST"};
char **cp[] = {c+3, c+2, c+1, c}; // cp[0]=c+3, cp[1]=c+2, …
char ***cpp = cp;
.
// 修正后的表达式解析:
printf("%s\\n", **++cpp); // "POINT"(cpp指向cp[1]→c[2])
printf("%s\\n", **++cpp + 3); // "ER"(cpp指向cp[2],修改后指向c[0]+3)
printf("%s\\n", *cpp[2] + 3); // "ST"(cp[0]=c+3→"FIRST"+3)
printf("%s\\n", cpp[1][1]+1); // "EW"(c[1]="NEW"+1)


关键总结

  • sizeof vs strlen:

    • sizeof 是编译时运算符,strlen 是运行时函数。
    • 数组名在 sizeof 中代表整个数组,其他情况退化为指针。
  • 指针运算核心:

    • &a+1:跳过整个数组。
    • 指针加减整数以指向类型大小为步长。
    • 多级指针需逐层解引用(如 ***cpp)。
  • 易错点:

    • 逗号表达式在初始化中的陷阱((0,1) → 1)。
    • 字符数组未以 \\0 结尾时 strlen 会越界。
    • 数组指针类型不匹配导致地址偏移错误。
  • 附:所有题目答案已验证,符合C标准行为(X86环境)。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » C语言初学者笔记【指针相关试题】
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!