如何理解 int * p_num = #

本文深入讲解了C语言中的指针概念及其应用。通过实例演示了指针的初始化、使用及如何通过指针修改变量值等内容。同时对比了Java与C语言中关于指针的不同之处。

OOP语言中,比如Java是没有指针这个概念的。或者说,在Java中,任何成员变量全部是指针。

但是在C语言中,有指针的概念。而且,C必须使用指针,不然很多东西无法表达了。那么,如何理解int * p_num = #呢?

    int num = 9;
    int * p_num = #

上面这两句代码,就完成了一个指针初始化的操作。但是上面这句话,很容易给人误导。让人困惑到底是给*p_num赋值为&num了还是给p_num赋值为&num了。但是,如果写成这样的:

    int num = 9;
    int * p_num;
    p_num = #

就很容易理解了。其实上面和下面这两种形式表达的含有是相同的。
但是如果是使用下面的方式,我们在使用*p_num的时候,就很放心地知道,当前这个变量的值是num,也就是9.

再看如何利用指针进行数据操作:

    // 间接运算符
    *p_num = 123;
    // *p_num 表示 取地址p_num的空间
    //  然后是赋值运算,将123 存放到P_num所指向的空间

    //这也就表明了现在 *p_num完全可以替代num进行对该空间做任何操作!

完整程序如下:

#include <stdio.h>

int main(void){
    // 指针的赋值方式一
//    int num = 9;
//    int * p_num;
//    p_num = &num;
//    printf("*p_num = %d , p_num = %p",*p_num,p_num);
    // 指针的赋值方式二
    int num = 9;
    int *p_num = &num;
    int* p1_num = &num;
    printf("*p_num = %d , p_num = %p , p1_num = %p\n",*p_num,p_num,p1_num);

    // 间接运算符
    *p_num = 123;
    // *p_num 表示 取地址p_num的空间
//    然后是赋值运算,将123 存放到P_num所指向的空间
//  这也就表明了现在 *p_num完全可以替代num进行对该空间做任何操作!
    printf("*p_num = %d , p_num = %p , p1_num = %p , *p1_num = %d\n",*p_num,p_num,p1_num,*p1_num);
    return 0;
}

完整输出如下:

*p_num = 9 , p_num = 0029ff04 , p1_num = 0029ff04
*p_num = 123 , p_num = 0029ff04 , p1_num = 0029ff04 , *p1_num = 123

Process returned 0 (0x0)   execution time : 0.463 s
Press any key to continue.
<think>嗯,用户问的是int *p = &num;这个语句是否等价于分开写的int *p; p = &num;。我需要仔细分析这两个语句的区别,尤其是在初始化和赋值阶段的不同。 首先,用户可能已经理解指针的基本概念,现在在深入学习初始化和赋值的区别。他们可能在学习过程中遇到了疑问,或者在代码中看到不同的写法,想确认是否等价。 接下来,我需要回忆C语言中变量声明和赋值的机制。声明时的初始化和之后的赋值是否完全一样?比如,初始化可能涉及更严格的类型检查,或者在某些情况下有不同的行为,比如const变量或者volatile变量。 然后,考虑具体的例子。int *p = &num; 这里p在声明时就被初始化,而分开的话是先声明再赋值。在大多数情况下,这两个操作是等效的,但有没有例外?比如当使用某些特定的修饰符时,比如extern,或者在结构体中的位域字段? 另外,需要检查是否有编译器优化的问题,或者是否可能在某些平台上导致不同的行为。不过通常来说,这两个写法在功能上是相同的,只是初始化更简洁,能减少错误,比如未初始化的指针。 还要想到用户可能的误解,比如是否初始化和赋值在内存分配上有不同,或者是否会影响程序的性能。这时候需要明确说明两者在结果上是一致的,但初始化更推荐,因为可以避免忘记赋值导致的错误。 最后,总结两者的异同,强调初始化更安全,代码更简洁,但功能上等价。同时指出可能的例外情况,比如使用某些特定类型或平台特性时,但一般情况下用户无需担心。</think>是的,`int *p = &num;` 在功能上**完全等价于**以下两行代码: ```c int *p; p = &num; ``` --- ### **等价性分析** 1. **最终结果一致**: - 两者均使指针 `p` 指向变量 `num` 的地址。 - 无论是初始化还是赋值,`p` 的值(即地址)和指向的数据类型(`int*`)完全相同。 2. **内存行为一致**: - 初始化和赋值操作均不会改变 `num` 的内存布局。 - 指针 `p` 的地址和指向的地址均一致。 3. **解引用行为一致**: ```c *p = 20; // 无论哪种写法,num 的值都会被修改为 20 ``` --- ### **关键区别(仅语法层面)** | 特性 | 初始化写法(`int *p = &num;`) | 分步写法(`int *p; p = &num;`) | |--------------------|-------------------------------|----------------------------------| | **代码简洁性** | 更简洁,一行完成声明和赋值 | 分两行,适合延迟赋值场景 | | **可读性** | 更清晰地表达意图(立即绑定) | 可读性稍弱,需跳转查看赋值位置 | | **错误风险** | 无未初始化指针风险 | 若忘记赋值,可能引发未定义行为 | --- ### **推荐用法** 1. **优先使用初始化写法**: - 避免未初始化指针的潜在错误(如 `int *p; *p = 10;` 会引发未定义行为)。 - 代码更紧凑,符合现代编程规范(如 C99/C11 的设计趋势)。 2. **分步写法的适用场景**: - 需要根据条件动态决定指针指向时: ```c int *p; if (condition) p = &num1; else p = &num2; ``` --- ### **验证示例** ```c #include <stdio.h> int main() { int num = 5; // 初始化写法 int *p1 = &num; printf("p1 = %p, *p1 = %d\n", (void*)p1, *p1); // 输出:p1 = 地址, *p1 = 5 // 分步写法 int *p2; p2 = &num; printf("p2 = %p, *p2 = %d\n", (void*)p2, *p2); // 输出与 p1 一致 } ``` --- ### **注意事项** - **类型匹配**:`&num` 的类型必须是 `int*`,否则会触发编译器警告或错误(如 `char num; int *p = &num;` 不匹配)。 - **常量性**:若 `num` 是 `const int`,则需用 `const int *p = &num;` 避免类型不匹配。 - **作用域问题**:若 `num` 是局部变量,指针 `p` 若在函数外使用会导致悬空指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值