C语言数组和指针的问题一道非常值得深思的笔试题

最近笔试就遇到下面这道题,谁都不敢说自己的C/C++能有多精通,当然,工作一久,很多老毛病也就容易犯了,所以说,理论是真的很重要的,下面这道题,说实话还是挺基础的,虽然当时笔试被我给猜对了,但还是要深究一下具体的转换细节。

如题:

#include <stdio.h>
int main(void)
{
 char *str[] = {"ab","cd","ef","gh","ij","kl"};
 char *t ;
 t = (str+4)[-1];
 printf("%s\n",t);
 return 0 ;
}

请问以上程序输出结果?程序正确运行结果如下:

我当时一看,数组下标还有负值?这是怎么一回事?我们把上面这个程序变一下,就很清晰了,如下:

#include <stdio.h>
int main(void)
{
 char *str[] = {"ab","cd","ef","gh","ij","kl"};
 char *t ;
// t = (str+4)[-1];
// printf("%s\n",t);
 t = (str+4)[0] ;
 printf("t:%s\n",t);
 return 0 ;
}

这个程序毫无疑问,答案就是ij。

看上面这幅图即可得到结果,其实就是这么一个转换关系:

实际上编译系统将数组元素的形式a[i]转换成*(a+i),然后才进行运算。对于一般数组元素的形式: <数组名>[<下标表达式>] 编译程序将其转换成:*(<数组名>+<下标表达式>),其中下标表达式为:下标表达式*扩大因子。整个式子计算结果是一个内存地址,最后的结果为:*<地址>=<地址所对应单元的地址的内容>。由此可见,C语言对数组的处理,实际上是转换成指针地址的运算。

所以,上面的式子的转换结果就是:t = *(str+4);

所以,t = (str+4)[-1] =======> t = *(str+4-1) ======> t = *(str+3) ;

所以:

#include <stdio.h>
int main(void)
{
 char *str[] = {"ab","cd","ef","gh","ij","kl"};
 char *t ;
// t = (str+4)[-1];
// printf("%s\n",t);
 t = *(str+4-1);
 printf("t:%s\n",t);
 return 0 ;
}

运行结果:

如果换种写法,如:

#include <stdio.h>
int main(void)
{
 int b ;
 int a[10] = {1,2,3,4,5,6,7,8,9,10};
 int *p = &a[0] ;
 b = (p+8)[-4];
 printf("b:%d\n",b);
 return 0 ;
}

你能知道答案是多少吗?一样的运算法则:

再接再励!!温故而知新,注重基础,一点细节也不要放过!

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

时间: 2018-12-15

C++实现动态数组功能

数组 数组是一种线性表数据结构.它用一组连续内存空间,来存储一组具有相同数据类型数据. 1.线性表:数据存储像一条线一样的结构,每个线性表上的数据最多只有前和后的两个方向,如数组.链表.队列.栈等都是这种结构,所以实现的数组的动态操作,其他结构也可轻易的类似实现.更重要的是,在这之后看源码就可大大降低难度.(博主自己看的是STL源码剖析) 2.非线性表:如二叉树.堆.图等. 3连续内存空间和相同数据类型:当数组作插入.删除操作时,为了保证数据的连续性,往往需要做大量的数据搬移工作,效率很低. 动

C语言数组按协议存储与按协议解析数据的实现

协议需求: (1)序列号(1个字节) 属性(1个字节) 名称(18个字节) (2)现有一块空间为600个字节,以20个字节为单位,分别存储以上数据,直到存满为止,并能解析. 根据协议,我们可以设计一个结构体来表述这些数据: struct Data_Info { char serial_num ; //序列号 char property ; //属性 char sample_name[18]; //分类名称 }; 恰恰在做嵌入式开发或者有关协议的开发就会要求类似这样的需求,我们可以写一个简单的C程

C语言数组栈实现模板

本文实例为大家分享了C语言数组栈实现模板的具体代码,供大家参考,具体内容如下 SeqStack.h #pragma once #define MAX_SIZE 1024 typedef struct SEQSTACK { void* data[MAX_SIZE]; int size; }SeqStack; SeqStack* Init_SeqStack(); // 初始化栈 void Push_SeqStack(SeqStack* stack, void* data); // 入栈 void*

php实现向javascript传递数组的方法

本文实例讲述了php实现向javascript传递数组的方法.分享给大家供大家参考.具体如下: 这里介绍的PHP进行数组传值给javascript的技巧,此方法适用php5.2以上,php5.2以上自带该类.低于5.2的,请下载json类.json是一种数据传输格式 php代码: $arr=array('1','2','3','4','5'): $str=json_encode($arr); echo "<input type='button' name='insert' value='I

jQuery中通过ajax调用webservice传递数组参数的问题实例详解

下面通过实例给大家说明比较直观些,更方便大家了解. 本人的项目中通过jquery.ajax调用webservice. 客户端代码如下: $.ajax({ url: "test/xxx.asmx", type: 'POST', dataType: 'xml', timeout: , data: { name: "zhangsan", tags: ["aa", "bb", "cc"] }, error: fun

C语言结构体数组同时赋值的另类用法

说到C语言结构体数组的同时赋值,许多人一想就会想到用以下的这种方法,咱们来写一个例子: #include <stdio.h> struct student { int a; int b ; int c ; }; struct student array1[1000] ; int main(void) { int i ; for(i = 0 ; i < 1000 ; i++) { array[i].a = 1 ; array[i].b = 2 ; array[i].c = 3 ; } fo

js传递数组参数到后台controller的方法

传递参数传递字符串,所以要把数组转换为字符串, var arr=[1,23,34,5]; var str = arr.toString(); str传递到后台,str.split(" , ");将字符串拆分得到元素. var arr=[1,23,34,5]; var str = arr.toString(); document.write(str); var getArr = str.split(","); for(var i=0;i<getArr.lengt

C++小知识:C/C++中不要按值传递数组

错误的代码: ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) { memcpy( mat, src, sizeof( src ) ); } 说明: 有时候程序员会忘记 C/C++ 里数组不能按值传递给函数.当你试图这样做时,是数组的指针(第一个元素的地址)而不是整个数组被传递.我们还应该记住,方括号中的数字没有任何意义.它们仅仅是程序员所做的标志,记录了传递数组的『假定』大小.事实上,你也可以传递一个大小完全不同的数组.例如,下面的代码就会成功编译

JavaScript实现shuffle数组洗牌操作示例

本文实例讲述了JavaScript实现shuffle数组洗牌操作.分享给大家供大家参考,具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"&g

JavaScript对JSON数组简单排序操作示例

本文实例讲述了JavaScript对JSON数组简单排序操作.分享给大家供大家参考,具体如下: 我们经常回使用到数据格式 var arr=[{num:1},{num:3},{num:2}] 如何根据数组里面的JSON数据的某个key进行排序 javascript有一个sort()方法,直接通过 arr.sort()进行排序,默认只对数组的值进行排序,然而以上的数组的值却是个JSON格式的. 我们在看看sort方法的定义: 定义和用法 sort() 方法用于对数组的元素进行排序. 语法 array

JavaScript数据结构之数组的表示方法示例

本文实例讲述了JavaScript数据结构之数组的表示方法.分享给大家供大家参考,具体如下: 数组类似于线性表.基本上每种语言都会讲数组作为固有类型.这里主要讲一下二维数组.我们可以把二维数组看成这样一个定长线性表:它的每个数据元素也是一个定长的线性表.数组一旦被定义,它的维数和维界就不再改变.因此,除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作(这里注意和JavaScript中的array类型做出区分,这里说的是数据结构,而不是某一种单独语言的语法). 由于数组一般不作插入或者

js实现json数组分组合并操作示例

本文实例讲述了js实现json数组分组合并操作.分享给大家供大家参考,具体如下: <script> var arr = [ {"id":"1001","name":"值1","value":"111"}, {"id":"1001","name":"值1","value":&qu

javascript数据结构之多叉树经典操作示例【创建、添加、遍历、移除等】

本文实例讲述了javascript数据结构之多叉树经典操作.分享给大家供大家参考,具体如下: 多叉树可以实现复杂的数据结构的存储,通过遍历方法可以方便高效的查找数据,提高查找的效率,同时方便管理节点数据.javascript的DOM其实就是以多叉树的形式存储的.下面用javascript来实现多叉树的数据结构 1.创造一个节点 数据是以节点的形式存储的: class Node { constructor(data) { this.data = data; this.parent = null;

JavaScript实现的简单加密解密操作示例

本文实例讲述了JavaScript实现的简单加密解密操作.分享给大家供大家参考,具体如下: JavaScript实现对内容的加密和解密.加密,转成编码.解密则是编码转字符串. <html> <head> <meta charset="utf-8" /> <title>www.jb51.net JS加密解密</title> </head> <body> <h1> 加密解密 </h1>

Java滚动数组计算编辑距离操作示例

本文实例讲述了Java滚动数组计算编辑距离操作.分享给大家供大家参考,具体如下: 编辑距离(Edit Distance),也称Levenshtein距离,是指由一个字符串转换为另一个字符串所需的最少编辑次数. 下面的代码摘自org.apache.commons.lang.StringUtils 用法示例: StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException StringUtils.getLevenshtei

JavaScript实现的反序列化json字符串操作示例

本文实例讲述了JavaScript实现的反序列化json字符串操作.分享给大家供大家参考,具体如下: JavaScript中如何反序列化json字符串呢? 有如下两种方法: (1) 使用万能的eval var jsonText = '{"name":"acwong","age":23,"address":{"province":"GuangDong","city":&

JavaScript使用prototype属性实现继承操作示例

本文实例讲述了JavaScript使用prototype属性实现继承操作.分享给大家供大家参考,具体如下: JS并没有显式的继承语法,在JS中所有的对象都是Object的子类实现, 因而对象之间是平等关系. 尽管如此我们可以通过特殊的方法达到继承的效果. 当然JS也不能直接定义类, 我们通过定义函数可以得到一个同名的类 , 同时这个函数就是这个类的构造器, 在定义函数时以this修饰的变量就是定义的 类的实例中的属性,当这个属性时函数时,  就可以认为这个属性变成了一个实例方法 //定义一个Pe

JS深入学习之数组对象排序操作示例

本文实例讲述了JS深入学习之数组对象排序功能.分享给大家供大家参考,具体如下: JavaScript实现多维数组.对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序. sort() 方法用于对数组的元素进行排序.语法如下: arrayObject.sort(sortby) 返回值为对数组的引用.请注意,数组在原数组上进行排序,不生成副本. 如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序.要实现这一点,首先应把数