C指针思考-(1)

首先记录下时间吧,@2016-08-18 23:26:22,这段时间看了同事的3本经典的书,《c缺陷和陷阱》,《c和指针》和《c专家编程》,感觉指针说的最多,多多少少还是有点领悟,记录下自己对指针的心得吧。

1.很多时候多说指针和数组是等效的。这句话是有条件的,由于最近在看c++方面的资料(c现在工作不好找啊),有了新的理解。

简单的来说,指针是一个间接寻址,而数组是直接寻址,在内存中,指针需要去一次地址后才能取到数据,而数组在内存中就是地址,直接根据地址就可以取到数据。所以在作为参数传递到函数中时,带入指针和带入数组,这个是等价的,因为传入的都是地址。这里我仔细想了想,某种意义上,指针也是传值操作,只不过类型是一个TYPE *而已,传入的是指向的那个地址(p的内容,也就是p的指向,也就是数据的地址,这里指针可以有很多理解,每段时间的理解都不一样,反正就是一个变量,存的是一个数据块的地址,指针根据这个地址去取数据)。

2.看高质量的c及c++编程指南--指针参数是如何传递内存的,这个好纠结,真的好纠结,我看完了,还是不敢说自己完全理解,只能记录自己理解的部分。

首先一个二级指针的描述吧

pp  -->  p  --> data in Mem

char *p = NULL;

p = (char *) malloc(10);

char **pp = NULL;

pp = &p;

其次是一个传值与传地址的理解吧,传值就是数据一个copy,传址就是变量在内存中地址传进去,很明显,可以改变地址里的内容,因而传指针和传数组都是能够改变传入的值的。

#include <stdio.h>

void InPt(char *p)
{
    printf("InPt p=[%s]\t *p=[%c] \t &p = [%d]\n", p, *p, &p);
}

void InArr(char p[])
{
    printf("InArr p=[%d]\t p[0]=[%c] \t &p[0] = [%d]\n", p, p[0], &p[0]);
}
int main(void)
{
    printf("Hello World!\n");

    char *p1 = "test";//这个是指向常量,分配在静态数据区,妄图改变是不可行的。
    //*p1 = ‘C‘; error here

    char arr[5]= "this";
    char *p = arr;
    printf("Main InArr arr=[%d]\t arr[0]=[%c] \t &arr[0] = [%d]\n", arr, arr[0], &arr[0]);
    printf("Main InPt p=[%s]\t *p=[%c] \t &p = [%d]\n", p, *p, &p);

    printf("*****\n");
    InArr(arr);
    InPt(p);

    printf("%s\n", p);

    return 0;
}

/*************Result:****************/

Hello World!
Main InArr arr=[2752167]         arr[0]=[t]      &arr[0] = [2752167]
Main InPt p=[this]       *p=[t]          &p = [2752160]
*****
InArr p=[2752167]        p[0]=[t]        &p[0] = [2752167]
InPt p=[this]    *p=[t]          &p = [2752144]
this

/*************end:****************/

可以看到  &p = [2752160]      &p = [2752160] 带进去的值是一样,但是装这个值的盒子(内存)却不一样,因为编译器为函数的参数制作值copy,所以我理解,传指针和传数组都是传‘值’,只不过这个值特殊而已,是一个地址而已。

林博士在《高质量的c及c++编程指南》举得例子:

void GetMemory(char *p, int num)

{

p = (char *)malloc(sizeof(char) * num);

}

void Test(void)

{

char *str = NULL;

GetMemory(str, 100);    // str 仍然为 NULL

strcpy(str, "hello");   // 运行错误

}

分析下GetMemory(str, 100)中str是一个指针,指针是间接取值,自身也占4个字节的空间,所以Test中的&str和GetMemory中的&p是两个盒子,只不过两个盒子中的东西一样而已,这某种意义上是传值,传的是盒子里的内容,指针这里很容易弄乱,至少我是这样的。其返回的任然是装指针的那个盒子,而这盒子并不是和主函数中的盒子一样,所以,分配不成功。

解决方法1:书中的一个是二级指针,带入chap **p,这样的话把盒子的地址传进去,在带出来.一级p指向data,其地址是二级p的内容,很明显二级就是传的一级指针的地址。

方法2:返回值传递动态内存

char *GetMemory3(int num)

{

char *p = (char *)malloc(sizeof(char) * num);

return p;

}

void Test3(void)

{

char *str = NULL;

str = GetMemory3(100);

strcpy(str, "hello");

cout<< str << endl;

free(str);

}

在堆上申请一块地址,p指向其,并返回p的地址。而后str指向这块地址,ok。

好了睡觉去。

时间: 2025-01-04 21:33:32

C指针思考-(1)的相关文章

合并_01php基础语法(8days)笔记

一.入门指引 1.php是什么? PHP是什么? Hypertext Preprocessor,超文本预处理器 Personal Home Page,个人主页 是一种在服务器端执行的脚本语言,可嵌入到 HTML中,尤其适合 web 开发. ? php可以做什么? 网站,web程序 B/S架构 ? ? 命令行脚本 桌面应用程序 ? ? 二.安装Apache 制作一台服务器,来提高网页服务,只要安装了一个能提供网页服务的软件的电脑,就可以称之为网页服务器. 常见的网页服务器软件 Apache IIS

java中传值及引伸深度克隆的思考(说白了Java只能传递对象指针)

java中传值及引伸深度克隆的思考 大家都知道java中没有指针.难道java真的没有指针吗?句柄是什么?变量地址在哪里?没有地址的话简直不可想象! java中内存的分配方式有两种,一种是在堆中分配,一种是在堆栈中分配,所有new出来的对象都是在堆中分配的,函数中参数的传递是在栈中分配的.通常情况下堆的内存可以很大,比如32位操作系统中的虚拟内存都可以被堆所使用(当内存紧张的时候甚至硬盘都可以是堆的存储空间),而堆栈的内存分配是有限的. 这和c++中内存分配差不多(c++中还要有另一种方式用于全

二维数组及二维指针的传递及一些思考

二维数组和二位指针在程序知识中是一个难点,往往会将人弄得头昏眼花.总结一下这个难点的相关问题. 二维数组,顾名思义就是数组的数组:二维指针是指针的指针.首先,我们来看看二维数组和二维指针等价的问题. 在<C专家编程>10.3节的小启发里讲的很透彻:(以下这段文字及对比一定要认真分析!) 数组和指针参数是如何被编译器修改的? "数组名被改写成一个指针参数"规则并不是递归定义的.数组的数组会被改写成"数组的指针",而不是"指针的指针":

由指针和引用的区别引发的思考

指针和引用一直在用,但是却从来没有仔细思考过他们真正的区别在哪里,一直都是照本宣科的理解,引用就是变量的别名,引用确定后就不能修改,原因是什么呢? 现在就来弄清楚事情的真相, 区别究竟在哪里? 下面这段话应该可以从本质上来解释指针和引用的区别 程序在编译的时候分别将指针和引用添加到符号表上, 符号表上记录的是变量,以及变量所对应的地址, 指针变量在符号表上对应的地址为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值, 符号表生成后就不会再改,因此指针可以改变其指向的变量地址. 而

w3周日__继续思考昨晚未尽的疑问(指针vs引用)

这波要针对上篇分析里 标红的问题(成员变量用 T,T&啥情况)继续思考, 要学习以下材料: 1. 知乎上:用指针还是引用 2. StackOverflow上的相关问题 https://stackoverflow.com/questions/12728794/why-should-i-use-reference-variables-at-all 3. Google:  What  is reference in Memory ;   When to use it; 4. String类型好像很特殊

C++ Primer 学习笔记与思考_7 void和void*指针的使用方法

(一)void的含义 void的字面意思是"无类型",void差点儿仅仅有"凝视"和限制程序的作用,由于从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错.提示"illegal use of type 'void'".只是.即使void a的编译不会出错.它也没有不论什么实际意义. void真正发挥的作用在于: (1) 对函数返回的限定: (2) 对函数參数的限定. int f(void); equal t

c++中函数中变量内存分配以及返回指针、引用类型的思考

众所周知,我们在编程的时候经常会在函数中声明局部变量(包括普通类型的变量.指针.引用等等). 同时,为了满足程序功能的需要,函数的返回值也经常是指针类型或是引用类型,而这返回的指针或是引用也经常指向函数中我们自己声明的局部变量. 这样,程序在某些情况下就可能存在一定的问题.看似很简单的问题,通过仔细的分析,我们就能够更好的理解c++中内存分配和释放的问题. 好,废话不多说,我们进入正题.首先,简单介绍一下程序的内存区域的分配: 程序的内存分配 ①堆区(heap).这一部分主要是由程序开发人员自己

二叉搜索树的实现及指针问题的一点思考(C++)

今天实现二叉搜索树的时候因为指针的问题卡了一上午(实在不应该...),一直segmentation fault,个人感觉还是需要记录一下的. 首先贴一下做的题的意思: 输入一系列整数,建立二叉排序数,并进行前序,中序,后序遍历.(jobdu 1201) 题目很简单,就是基本的二叉树的建立,最后代码如下 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 class node{ 5 public: 6 in

关于复杂指针数组,函数以及函数指针,数组思考

指针数组其实是数组,只不过是数组里面放着指针如int *p[],由于中括号的优先级高于星号,所以p先与中括号结合形成数组,然后再与星号结合形成指针数组,即每一个数组元素是一个指向整形数据的指针.而数组指针实际上是指向数组的指针如int(*p)[]. 同理函数指针是指向一个函数的指针,指针函数是说这个指针指向了一个函数如int(*fun)(int) ,而函数指针则意味着它是一个函数,这个函数的返回值是一个指针,如int * fun(intx).因此通过这个规律我们可以理解更深层次的更复杂的指针,