征服C指针(讲那么复杂,中国人永远都别想超越美国人)

一段永久掉坑的代码

#include <stdio.h>

void one_set(int num)
{
    num = 11;
}

void two_set(int *num) //掉坑一,蒙圈
{
    *num = 11; //掉坑二,泪奔
}

int main(void)
{
    int one = 1;
    int two = 2;
    one_set(one);
    two_set(&two); //掉坑三,又掉坑,没得救啦

    printf("one = %d; two = %d\n", one, two);
    return 1;
}

保存为demo.c 运行gcc -g demo.c -o demo然后执行./demo 输出结果是

one = 1; two = 11

结果没有错误,为什么掉坑

掉坑一:形参到底表示什么意思?two_set函数样子跟one_set一样,能看出区别吗?

大神说:不是有星号吗?看得出来是传入内存地址,不想跟傻逼聊天了!
我回复:那为啥你写的代码,不写成 void two_set(int* num) 更好

掉坑二:这赋值语句是啥?num就是普通数字,前面加个星号,是搞笑的吗?

大神说:指针的意思呀,num的指针指向11,用屁股想想都明白!
我回复:那为啥你写的代码,不写成 *addr = 11; 更好

掉坑三:我去,我就喜欢实参传入two,你就偏偏写成&two,气死人!

大神说:&这个符号,不懂就去学呗
我回复:我就偏偏不学,我要换另一种写法

与大神对话后,我换了另一种写法

#include <stdio.h>

void one_set(int num)
{
    num = 11;
}

void two_set(int* addr) //掉坑一,蒙圈
{
    *addr = 11; //掉坑二,泪奔
}

int main(void)
{
    int one = 1;
    int two = 2;
    int* twoAddr = &two;
    int threeAddr[] = {1,2,3};
    one_set(one);
    two_set(twoAddr); //掉坑三,又掉坑,没得救啦
    two_set(threeAddr);

    printf("one = %d; two = %d\n", one, two);
    printf("three[0] = %d; three[1] = %d\n", threeAddr[0], threeAddr[1]);
    return 1;
}

保存为demo.c 运行gcc -g demo.c -o demo然后执行./demo 输出结果是

one = 1; two = 11
three[0] = 11; three[1] = 2

解释为什么这样子写

  1. 变量加上Addr表示是地址的意思,two_set函数内容表达的意思特别清晰,即传入地址指向数字11。
  2. 书本表示数组,喜欢用arr[] = {1,2,3}。通过该代码threeAddr对比,发现书本上arr其实是地址的意思。
  3. 另外惊讶发现,two_set函数居然可以用于int和int数组,测试结果可以改变threeAddr数组第一个元素为11。
  4. 得出来结论:threeAddr数组是有连续3个地址,第一个地址是threeAddr,指向数字1。从而明白了内存结构。
*threeAddr threeAddr [0] 1
*(threeAddr+1) threeAddr [1] 2
*(threeAddr+2) threeAddr [2] 3

猜你喜欢

转载自blog.csdn.net/DongShiXiaRen/article/details/86070219