C:int型指针

本文探讨了C语言中的`int*`指针类型,包括直接寻址、间接寻址的概念,以及`int*`与一维、二维数组的关系。还涉及到了`int*`与`malloc`、`NULL`的使用,以及如何用`int**`模拟二维数组。同时,文章讲解了`const`修饰指针和指针数组的应用,并对比了不同函数返回指针类型的声明方式。最后提到了`char*`的相关内容。
摘要由CSDN通过智能技术生成
环境:mint 13 64bit,gcc 4.6.3。  
如无特殊,均为`gcc test.c -o test`的类似方式编译源文件。  

在这里主要讨论`int*`,`int**`,`char*`,`char**`等这些比较基本的指针类型,主要以int类型为示例。在64bit环境中地址用8B表示,int类型是4B。

关于直接寻址、间接寻址


参见相关汇编语言、计算机组成原理的书籍。

关于int *


`int *p`定以了一个整型指针变量p,p本身存放的是一个int变量的地址,即在32位机器上int变量为2Bytes,p实际为4Bytes,因为地址要用32bits表示。  
若有以下代码: 

#include <stdio.h>
int main()
{
    int *p;
    printf("%p\n",p);
    printf("%d\n",*p);
    return 1;                       
}
编译时会提示:`warning: ‘p’ is used uninitialized in this function [-Wuninitialized] `。  
运行时显示:
(nil)
Segmentation fault (core dumped)
这是因为声明p时候,分配的8个字节原先的内容并没有被抹去,故p指向的内容不定,甚至指向内核,这是OS不允许的。  
下面这段代码就可以正常运行:
#include <stdio.h>
int main()
{
    int i;  //默认初始化为0
    int *p=&i;
    printf("%p\n",&i);  //打印int变量i的地址
    printf("%p\n",&p);  //打印int指针变量p的地址
    printf("%p\n",p);   //打印p本身的内容
    printf("%d\n",*p);  //打印p本地代表的内存地址指向的值,即i的值。
    return 1;                       
}
运行结果为:(注意内存对齐的概念)
0x7fffcbaecf5c
0x7fffcbaecf50
0x7fffcbaecf5c
0
内存组织如下:从内存0x7fffcbaecf5c处开始4个Byte存放int变量i,从0x7fffcbaecf50开始的8个Byte开始int指针变量p的值,而这个值对应的内存单元在使用*p取值时只会取4个Byte。调用i时候类似直接寻址,调用`*p`时候类似间接寻址。因为p是`int`型指针。注意`int i;int*p=&i;`与`int i;int *p;p=&i;`是等价的,从这个角度来讲,可以把`int *`单独看作一种类型。虽然`int i;(int *)p=&i;`是错误的,但是比较容易理解(至少对我而言),例如在经典的交换数值问题上:
#include <stdio.h>
void swap(int *p1,int *p2);
int main()
{
    int i=0,j=1;
    swap(&i,&j);
    printf("i=%d,j=%d\n",i,j);
    return 1;                       
}
void swap(int *p1,int *p2)
{
    int temp;
    temp=*p2;
    *p2=*p1;
    *p1=temp;    
}
对于swap函数的参数`int *p1`,`int *p2`,只看p1、p2,两者是int型指针,本身代表地址。 所以调用的时候需要把地址填入里面,也就是&i、&j,注意i和j必须是int类型。  
在上面的swap代码修改如下:  
#include <stdio.h>
void swap(int *p1,int *p2);
int main()
{
    int i=0,j=1;
    printf("i addr:%p ,value:%d ; j addr :%p ,value:%d \n",&i,i,&j,j);
    swap(&i,&j);
    printf("i addr:%p ,value:%d ; j addr :%p ,value:%d \n",&i,i,&j,j);
    return 1;                       
}
void swap(int *p1,int *p2)
{
    printf("p1 value:%p , p2 value:%p ; *p1 value :%d , *p2 value:%d \n",p1,p2,*p1,*p2);
    int temp;
    temp=*p2;
    *p2=*p1;
    *p1=temp;   
    printf("p1 value:%p , p2 value:%p ; *p1 value :%d , *p2 value:%d \n",p1,p2,*p1,*p2);
}
输出可能如下:


i addr:0x7fff6ce4b608 ,value:0 ; j addr :0x7fff6ce4b60c ,value:1 
p1 value:0x7fff6ce4b608 , p2 value:0x7fff6ce4b60c ; *p1 value :0 , *p2 value:1 
p1 value:0x7fff6ce4b608 , p2 value:0x7fff6ce4b60c ; *p1 value :1 , *p2 value:0 
i addr:0x7fff6ce4b608 ,value:1 ; j addr :0x7fff6ce4b60c ,value:0
可以看出,在main()中调用swap()时
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值