c语言结构体指针,指针问题

C语言用指针对数组进行起泡法排序的问题_百度知道
C语言用指针对数组进行起泡法排序的问题
有两个错误,第一,paixu()函数,外层循环i从1开始到n-1第二,把*(p)改为*(p+j),把*(p+1)改为*(p+j+1)main函数没问题。以下程序是经过测试正确运行的,可供参考。#include &stdio.h&int paixu(int *p,int n){
int i,j,t;
for(i=1; i&n; i++)
for(j=0; j&n-i; j++)
if(*(p+j)&*(p+j+1))
*(p+j)=*(p+j+1);
*(p+j+1)=t;
}}void main(){
int *i,a[5];
printf(&input:\n&);
for(i=a; i&a+5; i++)
scanf(&%d&,i);
for(i=a; i&a+5; i++)
printf(&%d\n&,*i);
paixu(a,5);
for(i=a; i&a+5; i++)
printf(&%d\n&,*i);}
其他类似问题
为您推荐:
for(j=0;j&n-i;j++)不应该从0开始,而是从i的下一个开始
void paixu(int *p,int n){
int i,j,t;
for(i=0;i&n;i++)
for(j=0;j&n-i-1;j++)
if(*(p+j)&*(p+j+1))
*(p+j)=*(p+j+1);
*(p+j+1)=t;
修改如下:int paixu(int *p,int n){ int i,j,t; for(i=0;i&n;i++)
for(j=0;j&n-i-1;j++)
if(*(p+j)&*(p+j+1))
{t=*(p+j);*(p+j)=*(p+j+1);*(p+j+1)=t;}}
#include&stdio.h&void paixu(int *p,int n){ int i,j,t; for(i=0;i&n-1;i++) for(j=0;j&n-i-1;j++)
if(p[j]&p[j+1])
p[j]=p[j+1];
void main(){ int i,a[5]; printf(&input:\n&); for(i=0;i&5;i++)
scanf(&%d&,&a[i]); paixu(a,5); for(i=0;i&5;i++)
printf(&%3d&,a[i]);}
起泡法的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁当前访客身份:游客 [
当前位置:
#include &stdafx.h&
#define &ROWS 10
#define &COLS & &8
int count = 0;
void process_array(int **array){
for(i = 0; i & ROWS ; i ++){
for(j = 0; j& COLS; j ++){
*((*(array) + i) + j) = count++; &//无法读取内存
int _tmain()
int **array = (int **)malloc(sizeof(int) * ROWS * COLS);
process_array(array);
for(i = 0; i & ROWS; i ++){
for(j = 0; j& COLS; j ++){
printf(&%d &,*((*array + i) + j) );
& & printf(&\n&);
getchar();
如何使用二级指针作参数输出递增的整形数。
共有12个答案
<span class="a_vote_num" id="a_vote_num_
二级指针不是这么用的,你混淆了二级指针和二维数组。虽然二维数组在取其中的元素时采用了类似二级指针的做法。但是,数组和指针是两个完全不同的东西。
就你上面的程序,有几个错误的地方。
第一个就是 malloc 的分配内存的地方。malloc只返回一块内存,不管它用来存什么东西。分配时明明是想给它 rows * cols 个 int 类型的大小,但是返回时用的是 int** 指针。也就是说从类型匹配角度来说,你应该向这块内存里存 int*型 的数据。
第二个是 在process_array方法里,形参是二级指针,在给他赋值时步长是不对的。这里(*(array)+i)实际上只跳过了i 个内存块, 而不是你期望的 cols 个元素。
--- 共有 2 条评论 ---
(3年前)&nbsp&
thx,这其实不是我的代码,是一些关于二级指针的问题。我google了好多资料都没找到我想要的答案。你的答案很好,再次感谢!
(3年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
下次贴代码能不能专业一点?
<span class="a_vote_num" id="a_vote_num_
int **array = (int **)malloc(sizeof(int) * ROWS * COLS); 这句话有问题!
<span class="a_vote_num" id="a_vote_num_
调用和定义中都有问题。
首先malloc返回的是void * 。你需要给2级指针赋值,应该这么写
int * array = (int *)malloc(sizeof(int ) * ROWS * COLS);
int ** parray = &
调用的时候
process_array(parray);
最后,写入数组的操作,即For循环中无法写入内存的代码,改成这样。
(*parray)[i*COLS + j] = count++;
&这样应该就可以了,你试试吧。
<span class="a_vote_num" id="a_vote_num_
LZ你太有才了,内存都没分配你就搞起来了,我能跟你一样厉害么。
&申请内存 int * array = (int *)malloc(sizeof(int ) * ROWS * COLS); 函数调用 process_array(&array); 函数体 void process_array(int **array) { & if (0 == array || 0 == *array) & { &&&& && } && else & { &&&& for (int i=0;i&COLS;++i) &&&& { &&&&&&& for (int j=0;j&ROWS;++j) &&&&&&& { &&&&&&&&&& (*array)[i * ROWS + j] = count++;
&&&&&&&& } &&&&& } && } } 最后记得搞完后free
<span class="a_vote_num" id="a_vote_num_
奶奶的。。。每次遇到C的问题,我都没捞着新鲜的。。。。。。
--- 共有 1 条评论 ---
哈哈,这个遇不遇到问题,看来也是要看缘分的,没准下次你一不小心,打开网站,到处都是新鲜的,@ 你的,到时候你该头大了。
(3年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
引用来自“cut”的答案LZ你太有才了,内存都没分配你就搞起来了,我能跟你一样厉害么。
&申请内存 int * array = (int *)malloc(sizeof(int ) * ROWS * COLS); 函数调用 process_array(&array); 函数体 void process_array(int **array) { & if (0 == array || 0 == *array) & { &&&& && } && else & { &&&& for (int i=0;i&COLS;++i) &&&& { &&&&&&& for (int j=0;j&ROWS;++j) &&&&&&& { &&&&&&&&&& (*array)[i * ROWS + j] = count++;
&&&&&&&& } &&&&& } && } } 最后记得搞完后free一般是这么玩的:
int **create2Dint(int row,int col){
int ** re = 0;
if (row &= 0 || col &= 0)
re = (int**)malloc(row *col *sizeof(int) + row * sizeof(int *));
step = col * sizeof(int);
p[0] = (int*)(re + sizeof(int*)*row);
for (i = 1 ; i & i++){
p[i] = p[0] + i * col * sizeof(int);
--- 共有 1 条评论 ---
这个技巧性有点强,不过倒是挺适合上面的那个问题的。
(3年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
引用来自“中山野鬼”的答案引用来自“cut”的答案LZ你太有才了,内存都没分配你就搞起来了,我能跟你一样厉害么。
&申请内存 int * array = (int *)malloc(sizeof(int ) * ROWS * COLS); 函数调用 process_array(&array); 函数体 void process_array(int **array) { & if (0 == array || 0 == *array) & { &&&& && } && else & { &&&& for (int i=0;i&COLS;++i) &&&& { &&&&&&& for (int j=0;j&ROWS;++j) &&&&&&& { &&&&&&&&&& (*array)[i * ROWS + j] = count++;
&&&&&&&& } &&&&& } && } } 最后记得搞完后free一般是这么玩的:
int **create2Dint(int row,int col){
int ** re = 0;
if (row &= 0 || col &= 0)
re = (int**)malloc(row *col *sizeof(int) + row * sizeof(int *));
step = col * sizeof(int);
p[0] = (int*)(re + sizeof(int*)*row);
for (i = 1 ; i & i++){
p[i] = p[0] + i * col * sizeof(int);
你确定这个是LZ要的值?
--- 共有 2 条评论 ---
我知道你想搞什么啊,但这样搞不觉得很蛋疼,虽然你的是二维,但不是LZ要的。明显你那种写法要多申请点内存,而又不是做动态变长用的,没必要用那么蛋疼的写法。
(3年前)&nbsp&
和值没有关系,只是在构件一个二维空间,并用int **能使用。哈。你再琢磨琢磨。
(3年前)&nbsp&
<span class="a_vote_num" id="a_vote_num_
就这么区区几行代码,看着真够闹心的,二级指针你玩不起。
你给出了二维数组的ROWS, COLS宏定义,还整个二级指针出来耍,脑子进水了?直接int array[ROWS][COLS]不就完了,费那个鸟劲?
相信LZ没那么弱智,确实想整个长宽可变的二维数组,那你倒是把长宽作为变量往函数里传啦,整个宏出来,搞什么飞机!你看看人家野鬼怎么定义的:int **create2Dint(int row,int col),LZ学着点,最基本的东西,C语言伤不起!还有那个鸟屎全局变量count,莫名其妙!
再给你解释一下二维数组和二级指针的那点事。先看二维数组定义:
int a[3][5];
加入程序中出现对a[i][j]的访问,比如int d; d = a[i][j],编译器的做法类似于:
d = *(int *)(a + i * 5 + j);
也就是说,编译器会根据二维数组的长宽定义,对数组中元素的随机访问会转化成“基址 + 偏移量”的访问方式,而后者同样适用于二级指针的访问方式:
假设你定义二级指针指向一个长x宽 = row x col的二维数组:
对元素(i, j)的访问通过“基址+偏移量”完成:
d = *((int *)a + i * col + j);
d = *(int *)((unsigned char *)a + (i * col + j) *sizeof(int));
二维数组与指向二维数组的二级指针之间的差异在于:前者的随机访问编译器帮你搞定了,你写代码的方式更人性化了;后者的随机访问则需要你自己搞定,还有越界之类的判定也得自己掂量着办。
对指向二维数组的二级指针的访问接口定义大概可以这样,
int **create_array(const int row, const int col);
void& destroy_array(int **array);
int set_array(int **array, const int row, const int col, const int row_idx, const int col_idx, const int val);
int get_array(int **array, const int row, const int col, const int row_idx, const int col_idx);
这差不多是最小的接口集和参数表集。不过,够啰嗦对吧?
回头看看野鬼的代码,野鬼的做法是将二维数组存储分为指针区与数据区,指针区存储着二维数组中每行的头指针。随机访问元素(i,j)时,先通过i取得头指针p[i],然后通过*(p[i] + j)取得该元素——整个过程都是“基址+偏移量”,对不对?其实所有指针或数据的访问都是如此,这TMD是由计算机的本质决定的!还有一点,野鬼的代码其实有个非常好的出发点:把二级指针将为一级指针处理。这也是通行的、基本的做法:把多级指针降下来,一直降到一级指针为止,别TMD的跟我玩多级指针,你还真玩不起!LZ的问题完全可以用一级指针搞定,没必要整个二级指针折磨自己。
野鬼的代码里有两处错误,
p[0] = (int*)(re + sizeof(int*)*row);
p[i] = p[0] + i * col * sizeof(int);
各位想想为什么?
野鬼的代码仍然回答不了如何解决接口参数表太多的问题:如果通过接口随机访问某个元素,row, col必须作为参数传入。
几乎所有关于指针的困扰不过是庸人自扰,根源于对问题的描述力度不够,表现力度不够。
我们可以用面向对象的思想来封装和表达长宽不定的二维数组。先封装起来:
typedef struct
&& int data[0][0];&
typedef struct
&& int data[0];&
typedef struct
&& int **&
typedef struct
四种封装方式你会选择哪一种?
如果让我选,我就选第二或第四种,原因如前:不想庸人自扰,被二级指针困扰。
第二种封装方式意味着carray结构体与数据区紧邻,第四种封装方式意味着非紧邻,各有千秋,试具体情况选择。
接口定义如下:
carray *carray_new(const int row, const int col);
int carray_init(carray *array, const int row, const int col);
int carray_destory(carray *array);
int carray_set(carray *array, const int row_idx, const int col_idx, const int val);
int carray_get(carray *array, const int row_idx, const int col_idx);
<span class="a_vote_num" id="a_vote_num_
发现你们蛋疼得都可以称帝了,授予你们蛋疼帝的称号行不。
一个BUFF申请然后操作,其实可以参考下opengl的接口操作方式,我认为这样的接口才是最好的,
比如申请BUFF: &int GenArray(int x,int y); 返回的是BUFF对应内存池的ID,const char* GetArrData(int itargetID);返回BUF的数据指针。int GetArrayLen(int iTargetID)返回BUF数据的长度。int GetArrayAtI(int itarget,int x,int y,int* pOut);返回值时取值操作成功与否,pOut是穿出来的值。 用的人完全不用关心你怎么申请内存的,还有各种复杂的指针操作。这样的接口才是最合适的接口。
只要BUFF的指针一天以非常量指针存在都存在各种不安全的因素。比如这种int carray_get(carray *array, const int row_idx, const int col_idx); &看起来其实也没什么错,但外面传过来的指针,你函数内完全不知道实际该指针指向的空间是多少,虽然是取值函数,实际上程序员不知道会不会蛋疼的改里面的东西,作为接口设计者必须通过接口告诉写代码的。这个是不安全接口,一般用作取值的话,必须加const,这样才是安全接口。
--- 共有 1 条评论 ---
同意cut,这儿确实应该加上const
(3年前)&nbsp&
更多开发者职位上
有什么技术问题吗?
爱上绝对...的其他问题
类似的话题为什么说指针是 C 语言的精髓?
我实在想不出指针能有什么大作用难道是我悟性太差-_-麻烦举几个实例
按投票排序
日补充:我忽然觉得谈论“指针”的精髓性如何体现,这个问题太大,太宏观,太抽象。以至于我后面给出的都是些很具体的特性的举例说明。然而实际上我觉得实际上我还是未能回答好这个问题,或者说这个问题我的意会的体验还有限,思考也有限,所以不能很完美的从宏观上,较高的高度上回答好这个问题。所以我的答案,只能算作一种补充,一种参考。------这个问题有点“大”,所以以我的“肤浅”,要回答好这样一个“大”的问题着实不易。我也只能提到很片面的自我感受,供读者参考。我以为要更好的理解和使用指针,除了从高级语言角度学习,还应该适当参考一下汇编(机器码的助记形式),看它是如何操作和使用地址的。“指针是c的精髓”这样一个说法,不知道起源何处,可能并不是很科学很严谨,因为对指针的操作和使用是和实践结合在一起,很难把它单独拎出来论断其地位。这种说法可能和指针在 c,c++ 中的应用之广泛,依赖,而学习掌握的难度又较大有关。但它是必须掌握的是毋庸置疑的。------说精髓有点过了,有点玄乎了。c,c++是面向一个flat内存模型为基础,指针系出自天然。你看到的c++代码几乎都是和指针有关,几乎都是使用和操作指针。因为动态分配,传递数据结构,对象的参数几乎都是指针。(1)汇编和指令级别就有指针概念,所以c,c++里有指针是很自然的事。(2)配合内存管理,必须需要指针概念。(3)例如,文件的区块性加载或存储,一整块数据结构。其他语言因为OO了,你可能通常要一个字段一个字段来。(4)指向代码的指针:函数指针,是插件架构,不同人编写不同模块合作的基础。(5)c、c++中特有的半开口的可扩展内存。(6)指针和数组模型的天然无缝。其他的就没什么了,比如说指针的转型,虚函数表,这些把指针概念掩盖起来,其他语言也有对等。比如分配对象,释放对象,能够对程序员隐藏指针的概念。比如函数指针到了c#里成了委托,实际上还是函数指针概念更加直接。另外,一个指向某个地址的指针,和hold一个对象,两种概念之间,前者属于非常鲜明的面向内存模型的思维方式。这种思维方式和OO有时候可以等价,但有时候又有区别,可能需要你自己多加体会把。比如说,c语言里的字符串操作,基本上必须以前者作为思维方式,在c++里的string,因为c++需要你掌握太多细节,所以你要完全脱离前者的内存模型也几乎不可能,脱离了你可能会犯错。【补充】:只有把内存管理权交给程序员,C++程序才能做到内存的使用如此灵活和自由,才能达到高效。C++程序的内存分配策略可以是灵活而动态的,达到真正的按需分配,根据配置文件决定,这不是在编译期的傻傻的静态决定,而是运行期决定。需要负责内存管理的C++,自然也就是说,模型暴露的很底层,也就很自然也是形势必须的把指针概念传达到语言层面,交给程序员来控制。
1.因为搞不明白指针的人多,搞不懂东西就会被认为是精髓。2.因为有人说,又有人跟风,声势造大了就真的把它当精髓了。3.因为C和指针相关的知识点很多,所以被认为是精髓。4.因为可以依靠指针来实现很多东西,所以被认为是精髓。6.你来说7.你来说8.你来说...
指针这个概念是 c非常独特的一个地方。但指针这个东西却又不是 c 所独有的,基本上所有的语言都有指针的存在。为什么这么讲呢,通过一个例子来说明一下下面是从
java 的 LinkedList 实现中摘取出来的代表链表节点的数据结构。class Entry&E& {
E element;
Entry&E& next;
Entry&E& previous;
熟悉 c/c++ 的同学应该马上能看出差别。没错,如果是 c++ 的话,这个结构会是template &class E&
struct Entry {
E element;
Entry&E& *next;
Entry&E& *previous;
虽然 java 中没有指针,但 java 还是实现了c 中经典的链表。因为 java 中对于非内置类型的变量,都是采用引用的方式来访问。和 c++的引用不同,java 中的变量可以改变引用的对象,这实际上非常接近于c/c++中的指针。很多语言和 java 一样,都是以这种引用的方式来访问对象的。可以认为,这些引用都大致等同于 c 的指针。好了,既然大家都有各式各样的指针,那为啥还说指针是 c 语言的精髓?那是因为,c 语言的指针较之其他的指针要强大很多,举几个常见的例子:int value;
int array[10];
int *p = &value;
// 特定地址
int *pa = array;
// 特定的连续地址
int *pa1 = pa + 1;
int **pp = &p;
// 指针的指针
memset((void*)pa, 0, sizeof(array));
指针的超乎寻常的应用还有很多。可以说,指针使c具有和汇编几乎等同的数据访问能力,这是 c 被用于各种底层系统的一个重要原因。所以学习 c 的指针的概念,对于理解 c 这门语言,乃至理解整个计算机的原理都非常的重要。1.
简单来说,因为C就那点破feature,如果你把指针干掉,那这语言就完了。相反,如果你干掉struct,干掉union,干掉数组,甚至你把if-while都干掉,留下malloc和goto,则最多就是程序难写一点而已。所以这就是为什么C语言的精髓是指针了,因为他只有指针可以用了。
顺带解释几个精髓:asm: machine code is hard to r/wc: asm is too trivialc++: c doesn't have classjava: c++ has pointersjavascript: scheme doesn't like cnodejs: c is too low-level for asyn programmingclojure: java is not lisp本质上C是加了一层语法糖的汇编,引进当时先进的函数,保留了汇编强大的地址直接访问功能 —— 也就是所谓的指针功能,以增加操作灵活性。
在开发中,data structure 越复杂,算法就越简单。听说过 XML 的 parser 分为 SAX 和 DOM 两种吧?其中 SAX 就是 event-driven,没有 data structure,所以非常难用。听说过 one-pass compiler 和 multi-pass compiler 吧?前者几乎不用生成语法树,可是实现超级晦涩。有人问过 GPU 为什么那么快?GPU 没有 data structure,要求数据高度对其,所以那么快。可是把 CPU 算法改写成 GPGPU 超级难。Data structure 依靠的就是指针。不能靠内存的绝对位置表示数据的关系吧,那样的数据移动操作能把 data bus 都烧掉。
C 语言只有值的传递,无法直接传递引用,要想传递引用必须通过指针间接实现。如果 C 语言没有指针,一切都通过值传递,参数将永远只有输入参数,所有的结构体只要参与运算都具有极高的开销,因为每传递进函数参数一次就必须全体复制一次。另外一点:C语言无法在参数中传递数组,一切数组在函数参数传递时退化为指针,因此如果没有指针,数组将无法通过函数参数传递。还有一点,在C语言中函数是一个指针,如果没有指针,就无法定义C语言函数,无法使用和调用C语言函数,更无法将函数作为一个变量传递。——换句话说,没有指针,C语言将没有函数,一个没有函数的语言会是什么概念?实际上指针这概念在绝大多数高级语言中都普遍运用了,只是人家不叫指针,通常叫做引用而已。例如 Java 的所有对象变量从 C 语言的角度都实际上保存的是一个指针而不是对象本身。完全的舍弃指针,C程序将变得低效难懂,因为你无法让在任何子函数中修改一个结构体的内容。这种程序类似于无状态程序。我不知道指针算不算所谓“精髓”,但可以肯定的是没有指针的 C 语言几乎不可能进行任何有实际意义的正常的编程。甚至没有办法完整的实现 C 语言标准库。指针对 C 语言来说是必需品而非奢侈品。
C语言的指针,关键意思在于“指”。“指”是什么意思?其实完全可以理解为指示的意思。比如,有一个物体,我们称之为A。正是这个物体,有了这么个称谓,我们才能够进行脱离这个物体的实体而进行一系列的交流。将一个物体的指示,是对这个物体的抽象。有了这种抽象能力,才有所谓的智慧和文明。所以这就是“指示”这种抽象方法的威力。退化到C语言的指针,指针是一段数据/指令(在冯诺易曼体系中,二者是相通,在同一空间中的)的指示。这是指示,也就是这段数据/指令的起始位置。但是数据/代码是需要一个解释的方法的。比如0x0001,可以作为一个整数,也可以作为作为一串指令,也可以作为一串字符,总之怎样解释都可以。而C语言,在编译阶段,确定了这段数据/指令的“解释方法”。例如,整型指针,表示的就是可以从这个指针p指向的位置开始解释,解释为一个整数。一个函数指针,表示的就是可以从这个指针p指向的位置开始解释,解释为一段指令,对应的输入和输出以及返回值按照函数指针的类型,符合相应的要求。综上,C语言的精髓是指针,但指针不仅仅是C语言的精髓,它是抽象的精髓。各个语言中都有类似的东西,例如函数,例如引用。(引用和指针的区别,我的理解,不可以进行+/-偏移操作的指针,就是引用。随意偏移,很容易使得目标位置不符合其相应的意义,从而造成解释失败,进而崩溃。而增加了偏移功能的指针,好处是方便表述一堆具有相同类型的数据/指令,数组之类的就是这样的实例。)同样的void类型的指针,也是C语言的特色。void型的指针,就是去掉了指定类型的指针,从而使得可以以任意解释方式,解释指针,这就带来了如上的潜在问题。但是也可以说,这个C语言的特有威力(我一般都把C语言的威力理解为这个)。这个带来的好处非常之灵活。因为可以使用统一的类型来表述所有类型的数据。带来的问题,和上面是类似的。就是如果解释方法不当,就会造成灾难性的后果。C语言的强制类型转换也是打破常规的指针解释.也有可能带来问题.发现最后说偏了,但既然写上了,就放在这里吧。欢迎讨论。
指针的存在可以让程序直接操纵内存这在很多没有指针的程序设计语言中是做不到的因为可以直接操作内存,就有两点优势1、更灵活2、更高效
之所以说指针是C语言的精髓,在于,你会用指针、用好指针之后,能发挥C语言的强大威力;如果你不会用,C语言绝对不会比其他的任何一种语言好。举两个我自己比较熟悉的例子。一个是函数指针,比如一个计算一元实函数定积分的函数,可以写成如下形式double integrate( double (*f)( double x ), double lb, double ub );其中,lb是积分下界,ub是积分上界,f是被积函数(的指针)。这样就可以对所有double (*)(double x)形式的函数进行积分计算了。但是,如果是在Java中,实现这个功能可能就会比较麻烦。首先需要为这个计算积分的函数声明一个积分计算器的类,然后声明一个可积分的接口,能够被积分的函数的类需要继承并实现这个接口,然后再把这个被积函数的类的一个实例传给这个这个积分计算器进行计算....另外一个用得比较多的是结构体指针。如果只把结构体当成一个数据的集合的话,那么结构体并没有什么好用的。在处理二进制格式的数据,尤其是网络数据的数据包的时候,结构体指针非常好用。比如我们定义一个以太网帧首部的格式struct eth_header {unsigned char dst[6];unsigned char src[6];unsi};我们用socket读到一段二进制数据的时候,把指向该缓存的指针,用一个强制类型转换变成一个struct eth_header*类型的指针,那么这个数据包的内容就可以很容易的读出来了。比如读源地址,只需要这样unsigned char* buffer = .......struct eth_header* header = (struct eth_header*)printf( "SRC-MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",
header-&src[0], header-&src[1], header-&src[2],
header-&src[3], header-&src[4], header-&src[5] );这样的特性,在Java这些高级语言里面就比较难以做到。
据我所知,在高级语言里,C的指针是操纵硬件的唯一方式,有了指针你才能和真实的世界打交道。有人说我可以调操作系统的API来控制外面的设备,其实操作系统底层API(包括BSP),里面也是通过用指针去访问CPU的状态位、系统总线、各种卡的端口来实现的。有人说我发送信号产生系统中断也可以和外面交互,其实系统中断的时候是去调中断服务程序,里面也是大量的指针操作。归根结底还是指针操作。
澄清两点:1.通过指针能实现所谓的“传引用”而不是“传值”,本质上节约了数据传输性能2.光支持指针不是c出彩的地方,要支持指针的运算(对指针加减,甚至取指针)才是c类语言强大的地方。只支持传引用的语言大把大把。所以说前面很多回答的人都是一知半解,完全没有答到点子上。
写写汇编你就懂了。
指针,用熟了,就像东方不败手里的飞针,指哪打哪!你说是不是精髓?不用指针,你要从一个结构绕到另一个结构再绕到另一个结构,再绕啊绕的。。。如果指针滥用,就好比在火药库里面乱开枪,越灵活也就越危险
任何编程语言都有指针的---------一个程序要跳跃(为了找到使用的变量和改变执行顺序)。只是是不是显式调用罢了-----没有指针,只是那任务交给了语言本身内部机制罢了--------申请分配内存和消除内存的都是一样的。所谓的变量都是一样的。指针只是存了一份地址罢了,也就是地址就是它的内容。如果懂得计算机原理、汇编,这个不难理解。传值和传址是一回事,都是复制变量的内容,只不过是内容不同罢了---------指针的不同是它取出来的还是地址,有了地址我们就又可以访问并修改所指的内容。复制就是单纯的读操作,原来的还在,只是获得内容而已。-----------------我说,有些人是不是被国产的C语言的书给误导了呢?指针本来就是一个地址,本来意思就是引用------它本来就不是它所指的东西,它怎么传?要传不还是要通过指针访问,取出内容再传。面向对象语言也是有指针的。所谓的声明对象引用就是一个地址,而创建的对象是放在另一个地方的。C语言是显式调用指针的。也就是自己弄,自己消除。因为比汇编规范,所以更容易操作。汇编代码和变量是一样的,没有变量名强制规定,如果指错位置了就完全是另一个程序了------------C语言里,指针都会指向有意义的结构,避免了这种无标示符的困境------虽然会有越界等问题,但是逻辑上清晰了。同时因为没有过度的包装,所以更具有灵活性。语言越高级,它的结构就越复杂,当然也越规范---------说白点,就是功能都让别人给你实现了。指针是地址,只有使用地址才能改变要处理的对象,同时它没有规定的结构,所以内容有程序员自己设计;再则指针是C语言中最容易出问题的地方,这就是指针为什么是C语言的核心。
我认为你可以理解”效率是C语言的精髓“,通过指针可以直接对内存进行操作,故而效率高
有了指针的存在,就可以用短小的代码实现非常精巧的结构。
关键在于参数的传递吧。因为,我们知道,c语言在参数传递的时候,只有一种,那就是值传递类型。比如从函数A中跳到函数B中。我们调用函数B肯定是想为A服务的,但是现在跳到函数B中后,就是换了另外一个环境,所有的东西都是新的,它在栈上面重新分配了一块新的内存供函数B使用。所以从A传到B的变量只是在B中的栈中复制了一份,等到B调用完后,B中的所有东西,就没有了,销毁了,被OS回收了。所以A是找不到的。再来看,如果你想要B来该表A中的变量a,那么你只是把A中变量的值a传入B的话,你是白做的了,因为B中的a和A中的a知识值一样而已,它们是完完全全的两个变量啊,你对B中的a做了如何改变,丝毫不会影响A中的a的值。那么问题来了,怎么办?答案就是传递A中a的地址过去,因为A中a的地址是不变的啊,你在B中使用这个地址,依然是A中a的地址。所以,你传递&a过去,那么在B中操作这个地址,你就达到了改变A中a的值的目的。理解上面的过程,你必须对函数的调用过程很熟悉,包括函数栈,内存回收的知识,以及一个进程的内存分布情况。上面的传递过程还有一个优点:那么就是,如果变量a特别大,你只需要在B中复制一个地址值就可以了,这个代价是很小的。而且,如果你不想在B中改变a的值,你可以在传递的时候加上const关键字,任君选择。总之,指针是很灵活的用法,它的可用性在于在内存中每个存储单元的地址都是唯一的。
java也有“指针”啊,只不过自动解引用,为什么说是c的精髓,因为它的其他部分不够精髓。指针就是一个箭头,然后加上你自己的“幻想”,你可以幻想你指向的东西是任何类型,一个人,一条狗,等你要用到的时候才判定是不是你幻想的,可是大多数幻想容易产生错误,比如你觉得他是一只狗,可他是一个人。比如一下的typedef
struct {limbs
legs[4];//四条狗腿breast *//狗有好多乳房}typedef struct{limbs
hands[2];//两只手limbs legs[2];//两个人breast breasts[2];}((human *)&mydog)-&hands[0];((human *)&mydog)-&breasts[0];//报错你对一只狗取他的指针,然后硬要"幻想"他是一个人,然后真要拿他的时候可能错误,也可能不出错,比如你觉得某些人的手就是狗腿,你可以直接强行引用,"幻想"这时成真了,但在有些时候会出错。一个好处就是如果你实现的是某些库,或者某些算法,为了让他具有通用性,比如qsort(void *,size_t,size_t,void (*)(void * ,void *)),你可以让别的人去"幻想"他是任意的东西。所以用c你可以把狗变成人,把人看成狗,可以让人与狗排队。。。
首先为什么有「指针是C语言精髓」这个说法?在我看来,C语言之所以活到今天,一是因为它是最接近机器语言的可编程语言,二是它有大量前人优化好的的各种函数库。数据指针,函数指针,传值调用,定义链式数据结构确实是指针能做到的一些技巧,但是这些在其他后面的语言里面都有封装的更完善的使用方法。我反而觉得C语言的指针就像以前Basic里面的Goto,现在Javascript里面的callback一样(泛指一下不代表别的语言没有),是造成代码可读性变差,出错概率变高但是你又不能不忍受的东西。C语言的精髓还是他的函数式编程,还有算法和库。绝不是因为别的语言没有指针就说他的精髓是指针。这么说汇编的精髓就说寄存器操作?}

我要回帖

更多关于 c语言结构体指针 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信