学习
实践
活动
专区
工具
TVP
写文章

基础知识 | 每日一练(63)

学生:我遇到一些 “搞笑” 代码, 包含 5["abcdef"] 这样 “表达式”。这为什么是合法 C 表达式呢? 小林:数组和下标在 C言中可以互换。 这个奇怪事实来自数组下标的指针定义, 即对于任何两个表达式 a 和 e, 只要其中一个是指针表达式而另一个为整数, 则 a[e] 和 *((a)+(e)) 完全一样。 学生:既然数组引用蜕化为指针, 如果 arr 是数组, 那么 arr 和 &arr 又有什么区别呢? 小林:区别在于类型。 在标准 C 中, &arr 生成一个 “T 型数组指针, 指向整个数组。在 ANSI 之前 C 中, &arr 中 & 通常会引起一个警告, 它通常被忽略。 在所有的 C 编译器中, 对数组简单引用(不包括 & 操作符)生成一个 T 指针类型指针, 指向数组第一员。

2403029

我可能早就到阿里腾讯上班去了,如果早点知道这种学编程方法的话

首先我们应该先从C言中最基本概念开始(如果能将C言中基本概念与人类社会中一些基本概念联系起来的话,根据图灵计算原理,那么我这种想法很有可能也行得通)。 这就是我们说为什么指针C言中最重要概念原因(如果你还不明白,可以自己去百度一下图灵机)。 有了以上概念,那么我们就可以定义一些相对复杂东西,例如数组,我们知道数组是由许多单一数据类型组成集合,那么我们就可以将它类比一个小区,小区里由若干个人(变量)组成,而且每个人(变量)门牌号(地址 与现实中公司类似,如果一个公司(函数)十分庞大,甚至包含一个或几个街道,这时,如果函数想要使用结构体,只需知道结构体变量名以及其中成员名即可。 通过将人类社会工程学原理引入到C语言程序设计中,我们可以更好理解C言中一些概念,这可以降低初学者们学习时难度,同时也可以反窥C语言创造者们在编写C语言时逻辑历程,这对我们以后进行工程作业时可以有更多启发

40120
  • 广告
    关闭

    【玩转 GPU】有奖征文

    精美礼品等你拿!

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【编程基础】数组指针为什么不等价?

    好多初学C语言的人都认为数组指针是相等,在C言中数组指针困惑多数都来自这句话。说数组指针“等价”不表示它们相同, 甚至也不能互换。 它意思是说数组指针算法定义可以用指针方便访问数组或者模拟数组。 特别地, 等价基础来自这个关键定义: 一个T数组类型左值如果出现在表达式中会蜕变为一个指向数组第一个成员指针(有几种例外情况,下面会提及); 结果指针类型是T指针。 这就是说, 一旦数组出现在表达式中, 编译器隐式地生成一个指向数组第一个成员地指针, 就像程序员写出了&a[0] 一样。 而指针申明char *p, 请求一个位置放置一个指针, 用名称“p” 表示。这个指针几乎可以指向任何位置: 任何字符和任何连续字符, 或者哪里也不指。 一个图形胜过千言万

    66280

    深入 char * ,char ** ,char a ,char *a[] 内核

    http://blog.csdn.net/daiyutage/article/details/8604720    C言中由于指针灵活性,导致指针能代替数组使用,或者混合使用,这些导致了许多指针数组迷惑 char  str[10];           定义了一个有十个元素数组,元素类型为字符。          C言中定义一个变量时可以初始化。          由于C言中没有真正字符串类型,可以通过字符数组表示字符串,因为它元素地址是连续,这就足够了。          C言中规定数组代表数组所在内存位置首地址,也是 str[0]地址,即str = &str[0];          而printf("%s",str); 为什么用首地址就可以输出字符串。。           因此可以 s = a;        但是不能 a = s;        C言中数组名可以复制给指针表示地址, 但是却不能赋给给数组名,它是一个常量类型,所以不能修改。。

    1.9K20

    基础知识 | 每日一练(83)

    立业建功,事事要从实地着脚,若少慕声闻,便伪果;讲道修德,念念要从虚处立基,若稍计功效,便落尘情。 小林:C字符串用字符数组表示, 而 C 语言从来不会把数组作为一个整体操 作 (赋值, 比较等)。 上面代码段中 == 操作符比较是两个指针 —— 指针变量 string 值和字符串常数 “value” 指针值 —— 看它们是否相等, 也就是说, 看它 们是否指向同一个位置。 ; 为什么我不能写 char a[14]; a = "Hello, world!"; 小林:字符串是数组, 而你不能直接用数组赋值。 ; 学生:我怎么得到对应字符数字 (字符集) 值, 或者相反? 小林:在 C言中字符用它们字符集值对应小整数表示。因此, 你不需要任何 转换函数: 如有你有字符, 你就有它值。

    2573129

    C语言基础知识入门(大全)「建议收藏」

    C言中能被其他源文件调用函数称谓外部函数 ,外部函数由extern关键字来定义,形式为: extern [数据类型] 函数名([参数]) C语言规定,在没有指定函数作用范围时,系统默认认为是外部函数 所以,要想彻底理解指针,首先要理解 C言中变量存储本质,也就是内存。 在 C言中我们这样定义变量: int a = 999; char c = 'c'; 当你写下一个变量定义时候,实际上是向内存申请了一块空间来存放你变量。 实际上,我们是完全可以用 C 语言去模仿。 这就是为什么一直说 C 语言是基础,你真正懂了 C 指针和内存,对于其它语言你也很快理解其对象模型以及内存布局。 为什么这样呢? 站在编译器角度讲,变量名、数组名都是一种符号,它们都是有类型,它们最终都要和数据绑定起来。

    77340

    语法分析器(Parser)实现

    Opcode ==> ExprAST *Result = new BinExprAST("+",X,Y); 这就可以看出为什么有两个ExprAST类型指针,因为他们分别执行运算符两端数据:X与 按照通常数学定义,我们期望解析后者,因为“*”(乘法)优先级要高于“+”(加法)。 这个问题解法很多,其中属运算符优先级解析最为优雅和高效。 这里map简化了新运算符添加,同时也可以证明我们算法与具体运算符无关。当然,要想去掉map直接在GetTokPrecedence中比较优先级也很简单。(甚至可以直接使用定长数组)。 它参数包括一个整数和一个指针,其中整数代表运算符优先级,指针则指向当前已解析出来那部分表达式。 该调用完整解析出上述示例中“(c+d)*e*f”,并返回构造出AST节点,这个节点就是“+”表达式右侧RHS。 最后,while循环下一轮迭代将会解析出剩下“+g”并将之纳入AST。

    56230

    为什么指针被誉为 C 语言灵魂?

    C言中我们这样定义变量: int a = 999; char c = 'c'; 当你写下一个变量定义时候,实际上是向内存申请了一块空间来存放你变量。 也就是在 C言中如何表示地址这个概念呢? 对,就是指针,你可以这样: int *pa = &a; pa 中存储就是变量 a 地址,也叫做指向 a 指针。 实际上,我们是完全可以用 C 语言去模仿。 这就是为什么一直说 C 语言是基础,你真正懂了 C 指针和内存,对于其它语言你也很快理解其对象模型以及内存布局。 为什么这样呢? 站在编译器角度讲,变量名、数组名都是一种符号,它们都是有类型,它们最终都要和数据绑定起来。 void 还可以用来实现 C言中多态,这是一个挺好玩东西。

    45910

    一篇文章完全讲解C语言指针

    指针对于C来说太重要。然而,想要全面理解指针,除了要对C语言有熟练掌握外,还要有计算机硬件以及操作系统等方方面面的基本知识。所以本文尽可能通过一篇文章完全讲解指针为什么需要指针? 我们知道:C言中数组是指一类类型,数组具体区分为 int 类型数组,double类型数组,char数组 等等。 C言中程序数据按照他们定义位置,数据种类,修饰关键字等因素,决定他们生命周期特性。 实质上我们程序使用内存会被逻辑上划分为:栈区,堆区,静态数据区,方法区。 在C言中,我们让指针变量赋值为NULL表示一个空指针,而C言中,NULL实质是((void*)0),就像前面说指针可以理解特殊int,它总是有值,p=NULL,其实就是p值等于0。 指针常用在C言中,而引用,则用于诸如Java,C#等 在语言层面封装了对指针直接操作编程语言中

    48820

    C++初阶】类和对象修炼上

    封装:隐藏属性,公开行为接口 也就是将想给你访问成员函数定义私有,不想给你访问成员变量定义私有,将成员变量定义私有之后,在类外你不能随意访问我们成员变量,这样就不用担心成员变量被修改了,你要想修改成员变量的话 ,成员函数放在公共代码段中 优点:节约了空间.猜想合理且成立 ps:其实仔细一想我们也能理解,我们在C言中写函数目的就是为了防止重复造轮子,打印你这个数组和打印我这个数组,其实都可以只调用一个函数 ArrayPrint(),只需要传入各自数组名和数组元素个数即可打印出各自数组(只不过在C++中这里参数变成了隐含this指针,后面第9点会讲) 8.类/对象大小 通过上面的知识点,我们已经知道 那里我们知道了成员函数存储位置是公共代码段,成员函数是共享使用: C言中对于打印数组1和数组2,只需显式传入各自数组名和数组大小即可打印出各自数组. this指针是“成员函数”第一个隐含指针形参,一般情况由编译器通过ecx寄存器自动传 递,不需要用户传递 其实:我们细想一下,我们在学C语言时候,对于传参,我们一般都是选择传一个变量(比如栈或数组

    17040

    Golang中interface内部构造与面试真题分析

    (People为interface类型,就是指针类型) 二、interface内部构造(非空接口iface情况) 01 以下代码打印出来什么内容,说出为什么? (go语言中特殊指针类型unsafe.Pointer类似于c言中void*) } _type属性:是GO语言中所有类型公共描述,Go语言几乎所有的数据结构都可以抽象 _type,是所有类型公共描述 表示指向具体实例数据指针,他是一个unsafe.Pointer类型,相当于一个C万能指针void*。 fun字段其实是一个动态大小数组,虽然声明时是固定大小为1,但在使用时会直接通过fun指针获取其中数据,并且不会检查数组边界,所以该数组中保存元素数量是不确定。 ) People { var stu *Student return stu } stu是一个指向nil指针,但是最后return stu 触发匿名变量 People = stu

    23120

    数组不可以直接赋值,为什么结构体中数组却可以?

    一、前言 二、数组各种操作 1. 错误方式 2. 利用结构体来复制数组 3. 其他复制方式 三、语言标准和编译器 1. 数组指针关系 2. 为什么不能对数组赋值 3. 函数形参是数组情况 4. 为什么结构体中数组可以复制 5. 参数传递和返回值 五、总结 一、前言 在 C/C++ 语言中数组类型变量是不可以直接赋值。 也就是说,目前标准中对于数组操作方式,是利大于弊。 既然标准已经是制定这样了,我们就来分析一下编译器是如何来遵循、实现这个标准。 1. 数组指针暧昧关系 很多人都这样记忆:数组名就是数组开始地址指针。这是不对,或者说不严谨。 在 C/C++ 中,数组就是数组指针就是指针。 printf 中,a “临时”代表指向第一个元素常量指针

    1.5K30

    C++打怪 之 vector

    但是设置过大,也导致内存浪费,虽然不是什么大问题,但这种变量若定义过多,也导致一笔不小开销。在C言中,可以通过动态数组来解决这一问题。但是在一些场景中,用起来较为复杂。 按我理解,C++中「vector」 与 C指针 + malloc」 类似。只不过vector将动态数组一系列操作都封装成标准库接口。 如果我们将「vector」理解*「vector + malloc」 ,就能够分析出以上问题原因: 第一个问题理解。vector是一个指针,如果没有初始化赋值,就是一个野指针。 那么在使用没有初始化vector,就如同在使用野指针导致宕机。 第二个问题理解。 总结 c++中vector解决了C言中声明数组时无需确定范围,其实现方式类似于C言中动态数组。不过较C++实现了vector各种接口,其接口功能看起来也比较符合动态数组功能。

    64520

    CGO学习二,基本数据类型转换2 和 函数调用

    3 个咱们在上一篇短文已经梳理到了,接下来继续 数组类型 C 语言里面: 数组 C 语言里面,数组名对应一个指针,指向特定类型特定长度一段内存,但是这个指针不能被修改 C语言字符串是一个char类型数组 go byte 类型数组(切片),克隆并转换成 C 语言指针指针是一个数组,需要开辟空间,不用时候,也是需要手动释放 func C.GoString(*C.char) string C.GoString 将 C 字符串克隆 GO string , GO 里面自己释放内存 func C.GoStringN(*C.char, C.int) string C.GoStringN ,将C 具体某个长度字符串转换成 GO string, GO 里面自己释放内存 func C.GoBytes(unsafe.Pointer, C.int) []byte C.GoBytes 将 C 数组,转换成 GO 切片 C 语言里面: 指针C 语言灵魂,C 语言里面,不同类型指针间可以强制转换,指针自由转换也是 cgo 代码中经常要解决第一个重要问题 GO 语言里面: 不同类型转换非常严格,任何 C言中可能出现警告信息在

    18630

    C语言和C++区别和联系

    面向对象:面向对象编程就是把问题分解各个对象,建立对象目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题步骤中行为。 7、const C言中被const修饰变量不是常量,叫做常变量或者只读变量,这个常变量是无法当作数组下标的。 然而在C++中const修饰变量可以当作数组下标使用,成为了真正常量,这就是C++对const扩展。 C言中const:被修饰后不能做左值,可以不初始化,但是之后没有机会再初始化。 不可以当数组下标,可以通过指针修改。 简单来说,它和普通变量区别只是不能做左值而已,其他地方都是一样C++中const:真正常量。定义时候必须初始化,可以用作数组下标。 const在C++中编译规则是替换(和宏很像),所以它被看作是真正常量。也可以通过指针修改。需要注意是,C++指针有可能退化成C语言指针

    24210

    C语言三剑客之《C专家编程》一书精华提炼

    这也是为什么C++语言令人失望原因:它对C言中存在一些最基本问题没有什么改进,而它对C语言最重要扩展(类)却是建立在脆弱C类型模型上。 如数组越界。 指针释放引起错误。 第8章-- 为什么程序员无法分清万圣节和圣诞节 很无厘头开始。 类型提升:在任何表达式中,并不局限于涉及操作符和混合类型操作数表达式。 在C言中,有好几种方法可以用来表达FSM,但他们绝大多数都是基于函数指针数组。 我觉得编译器可以打开一个选项,是否检查数组越界访问。 把作为形参数组指针等同起来是出于效率原因考虑。在C言中,所有非数组形式数据实参均以传值形式。 (注意,只有把二维数组改为一个指向向量指针数组前提下才可以这么做!) 在C言中,传递多维数组必须提供除最左面一维以外所有维长度。

    1.3K50

    对比 C++ 和 Python,谈谈指针与引用

    点击上方蓝字“Python猫”,免费获得一个公众号 花下猫:本文是学习群内樱雨楼小姐姐投稿。之前已发布过她一篇作品《当谈论迭代器时,我谈些什么?》,大受好评。 本文依然是对比 C++ 与 Python,来探讨编程语言中极其重要概念。祝大家读有所获,学有所! 本文基于 C++ 与 Python,讨论了 Python 中与指针及引用相关一些行为。1 什么是指针为什么需要指针? 如果一个指针缺少指针类型,即 void *,则显然,其虽然保存了内存地址,但这仅仅是一个起点地址,指针因为无法获知从起点向后进行偏移量,从而拒绝解指针操作;而如果一个指针缺少地址,即 nullptr 2 C++中引用在 C++ 中,引用具有与指针相似的性质,但更加隐形与严格。C++ 引用分为以下两种:2.1 左值引用左值引用于其初始化阶段绑定到左值,且不存在重新绑定。

    85720

    C 语言指针最详尽讲解

    指针对于C来说太重要。然而,想要全面理解指针,除了要对C语言有熟练掌握外,还要有计算机硬件以及操作系统等方方面面的基本知识。所以本文尽可能通过一篇文章完全讲解指针为什么需要指针? 我们知道:C言中数组是指一类类型,数组具体区分为 int 类型数组,double类型数组,char数组 等等。 C言中程序数据按照他们定义位置,数据种类,修饰关键字等因素,决定他们生命周期特性。 实质上我们程序使用内存会被逻辑上划分为:栈区,堆区,静态数据区,方法区。 当把数组名赋值给一个指针后,再对指针使用sizeof运算符,返回指针大小。 这就是为什么将一个数组传递给一个函数时,需要另外用一个参数传递数组元素个数原因了。 指针常用在C言中,而引用,则用于诸如Java,C#等 在语言层面封装了对指针直接操作编程语言中

    32840

    C语言和C++区别和联系

    面向对象:面向对象编程就是把问题分解各个对象,建立对象目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题步骤中行为。 7、const C言中被const修饰变量不是常量,叫做常变量或者只读变量,这个常变量是无法当作数组下标的。 然而在C++中const修饰变量可以当作数组下标使用,成为了真正常量,这就是C++对const扩展。 C言中const:被修饰后不能做左值,可以不初始化,但是之后没有机会再初始化。 不可以当数组下标,可以通过指针修改。 简单来说,它和普通变量区别只是不能做左值而已,其他地方都是一样C++中const:真正常量。定义时候必须初始化,可以用作数组下标。 const在C++中编译规则是替换(和宏很像),所以它被看作是真正常量。也可以通过指针修改。需要注意是,C++指针有可能退化成C语言指针

    1.4K30

    C语言指针详解

    我们指知道:C言中数组是指 一类 类型,数组具体区分为  int 类型数组,double类型数组,char数组 等等。 C言中程序数据按照他们定义位置,数据种类,修饰关键字等因素,决定他们生命周期特性。实质上我们程序使用内存会被逻辑上划分为:   栈区,堆区,静态数据区,方法区。 空指针  指向空,或者说不指向任何东西。在C言中,我们让指针变量赋值为NULL表示一个空指针,而C言中,NULL实质是 ((void*)0) ,  在C++中,NULL实质是0。   当把数组名赋值给一个指针后,再对指针使用sizeof运算符,返回指针大小。  这就是为什么我么将一个数组传递给一个函数时,需要另外用一个参数传递数组元素个数原因了。   指针常用在C言中,而引用,则用于诸如Java,C#等 在语言层面封装了对指针直接操作编程语言中

    51920

    扫码关注腾讯云开发者

    领取腾讯云代金券