匿名用户

1级

2011-11-04 回答

NEW是C 的关键字,能进行类型的检查之类的

malloc是C跟C 都可以用的

不能进行类型检查之类

如果是在C 中,推荐使用new

inline函数区别与普通函数在于调用普通函数时程序有压栈和出栈操作,而inline(内联)函数编译器在预处理的时候会把它的代码加到调用它的函数中,而不用额外的跳转操作,从而提高了程序的效率。

但是inline不允许有switch, 循环等复杂语句。

堆,可用NEW对它分配内存,DELETE销毁内存空间。

栈,是由程序本身建立,分配,消除的内存空间!他服从先进后出(FILO)的原则,从而可以把各个变量按生存期分开!

static 声明的变量在C语言中有两方面的特征:

1)、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。

2)、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。

Tips:

A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;

B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;

C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;

D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数)

E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。

函数前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。

扩展分析:术语static有着不寻常的历史.起初,在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量。随后,static在C中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。为了避免引入新的关键字,所以仍使用static关键字来表示这第二种含义。最后,C 重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数(与Java中此关键字的含义相同)。

全局变量、静态全局变量、静态局部变量和局部变量的区别变量可以分为:全局变量、静态全局变量、静态局部变量和局部变量。

按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。

按作用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。

从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。

static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;

static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;

static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。

C 中extern “C”含义深层探索

1.引言

C 语言的创建初衷是“a better C”,但是这并不意味着C 中类似C 语言的全局变量

和函数所采用的编译和链接方式与C 语言完全相同。作为一种欲与C 兼容的语言,C 保留了

一部分过程式语言的特点,因而它可以定义不属于任何类的全局变量和函数。但是,C 毕竟

是一种面向对象的程序设计语言,为了支持函数的重载,C 对全局函数的处理方式与C 有明

显的不同。

2.从标准头文件说起

某企业曾经给出如下的一道面试题:

面试题

为什么标准头文件都有类似以下的结构?

#ifndef _TEST_H

#define _TEST_H

#ifdef __cplusplus

extern "C" {

#endif

/*...*/

#ifdef __cplusplus

}

#endif

#endif /* _TEST_H */

分析

显然,头文件中的编译宏“#ifndef _TEST_H、#define _TEST_H、#endif” 的作用是防止

该头文件被重复引用。

那么

#ifdef __cplusplus

extern "C" {

#endif

#ifdef __cplusplus

}

#endif

的作用又是什么呢?

3.深层揭密extern "C"

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;

其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。

被extern "C"限定的函数或变量是extern 类型的;

extern 是C/C 语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告

诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:

extern int a;

仅仅是一个变量的声明,其并不是在定义变量a,并未为a 分配内存空间(特别注意:实

际上现在一般的编译器都会对上述语句作声明处理,但链接器在链接过程中如果没有发现该

变量的定义,一般会在第一次遇到该变量声明的地方,自动定义)。变量a 在所有模块中作为

一种全局变量只能被定义一次,否则会出现连接错误。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字

extern 声明。例如,如果模块B 欲引用该模块A 中定义的全局变量和函数时只需包含模块A

的头文件即可。这样,模块B 中调用模块A 中的函数时,在编译阶段,模块B 虽然找不到该

函数,但是并不会报错;它会在连接阶段中从模块A 编译生成的目标代码中找到此函数。

与extern 对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因

此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

被extern "C"修饰的变量和函数是按照C 语言方式编译和连接的;

未加extern “C”声明时的编译方式

首先看看C 中对类似C 的函数是怎样编译的。

作为一种面向对象的语言,C 支持函数重载,而过程式语言C 则不支持。函数被C 编

译后在符号库中的名字与C 语言的不同。例如,假设某个函数的原型为:

void foo( int x, int y );

该函数被C 编译器编译后在符号库中的名字为_foo,而C 编译器则会产生像

_foo_int_int 之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,

生成的新名字称为“mangled name”)。

_foo_int_int 这样的名字包含了函数名、函数参数数量及类型信息,C 就是靠这种机制

来实现函数重载的。例如,在C 中,函数void foo( int x, int y )与void foo( int x, float

y )编译生成的符号是不相同的,后者为_foo_int_float。

同样地,C 中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的

类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函

数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全

局变量名字不同。

未加extern "C"声明时的连接方式

假设在C 中,模块A 的头文件如下:

// 模块A 头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

int foo( int x, int y );

#endif

在模块B 中引用该函数:

// 模块B 实现文件 moduleB.cpp

#i nclude "moduleA.h"

foo(2,3);

实际上,在连接阶段,连接器会从模块A 生成的目标文件moduleA.obj 中寻找

_foo_int_int 这样的符号!

加extern "C"声明后的编译和连接方式

加extern "C"声明后,模块A 的头文件变为:

// 模块A 头文件 moduleA.h

#ifndef MODULE_A_H

#define MODULE_A_H

extern "C" int foo( int x, int y );

#endif

在模块B 的实现文件中仍然调用foo( 2,3 ),其结果是:

(1)模块A 编译生成foo 的目标代码时,没有对其名字进行特殊处理,采用了C 语言的

方式;

(2)连接器在为模块B 的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A 中函数声明了foo 为extern "C"类型,而模块B 中包含的是extern int

foo( int x, int y ) ,则模块B 找不到模块A 中的函数;反之亦然。

所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特

性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留

在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入

地理解许多问题):

实现C 与C 及其它语言的混合编程。

明白了C 中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧。

4.extern "C"的惯用法

(1)在C 中引用C 语言中的函数和变量,在包含C 语言头文件(假设为cExample.h)

时,需进行下列处理:

extern "C"

{

#i nclude "cExample.h"

}

而在C 语言的头文件中,对其外部函数只能指定为extern 类型,C 语言中不支持extern

"C"声明,在.c 文件中包含了extern "C"时会出现编译语法错误。

笔者编写的C 引用C 函数例子工程中包含的三个文件的源代码如下:

/* c 语言头文件:cExample.h */

#ifndef C_EXAMPLE_H

#define C_EXAMPLE_H

extern int add(int x,int y);

#endif

/* c 语言实现文件:cExample.c */

#i nclude "cExample.h"

int add( int x, int y )

{

return x y;

}

// c 实现文件,调用add:cppFile.cpp

extern "C"

{

#i nclude "cExample.h"

}

int main(int argc, char* argv[])

{

add(2,3);

return 0;

}

如果C 调用一个C 语言编写的.DLL 时,当包括.DLL 的头文件或声明接口函数时,应加

extern "C" 。

(2)在C 中引用C 语言中的函数和变量时,C 的头文件需添加extern "C",但是在C

语言中不能直接引用声明了extern "C"的该头文件,应该仅将C 文件中将C 中定义的extern

"C"函数声明为extern 类型。

笔者编写的C 引用C 函数例子工程中包含的三个文件的源代码如下:

//C 头文件 cppExample.h

#ifndef CPP_EXAMPLE_H

#define CPP_EXAMPLE_H

extern "C" int add( int x, int y );

#endif

//C 实现文件 cppExample.cpp

#i nclude "cppExample.h"

int add( int x, int y )

{

return x y;

}

/* C 实现文件 cFile.c

/* 这样会编译出错:#i nclude "cExample.h" */

extern int add( int x, int y );

int main( int argc, char* argv[] )

{

add( 2, 3 );

return 0;

}

如果深入理解了第3 节中所阐述的extern "C"在编译和连接阶段发挥的作用,就能真正

理解本节所阐述的从C 引用C 函数和C 引用C 函数的惯用法。对第4 节给出的示例代码,

需要特别留意各个细节。

volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。

例如:

volatile int i=10;

int j = i;

...

int k = i;

volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。

而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。

断言(assert)是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为 true。如果表达式计算为 false,那么系统会报告一个 Assertionerror。它用于调试目的:

assert(a

c语言item变量,C++ 中的Item是什么关键字?可以定义什么型的变量?相关推荐

  1. python 类可以调用实例变量_python中的实例方法、静态方法、类方法、类变量和实例变量浅析...

    注:使用的是Python2.7. 一.实例方法 实例方法就是类的实例能够使用的方法.如下: class Foo: def __init__(self, name): self.name = name ...

  2. python item方法_Python中使用item()方法遍历字典的例子

    Python字典的遍历方法有好几种,其中一种是for...in,这个我就不说明,在Python了几乎随处都可见for...in.下面说的这种遍历方式是item()方法. item() item()方法 ...

  3. java开发定义一个好的变量名

    如何定义一个好的变量名 在日常编程中最烦恼的就是给变量取名,一段好代码,既要能完美地运行,还要能较容易地维护.这就意味着需要让日后维护代码的人能很快地看懂你的代码,而且,在团队合作中,其他开发者也会经 ...

  4. (转载) 如何定义一个号的变量名

    如何定义一个好的变量名 在日常编程中最烦恼的就是给变量取名,一段好代码,既要能完美地运行,还要能较容易地维护.这就意味着需要让日后维护代码的人能很快地看懂你的代 码,而且,在团队合作中,其他开发者也会 ...

  5. (转)字符型指针变量与字符数组的区别

    (1)分配内存 设有定义字符型指针变量与字符数组的语句如下: char *pc ,str[100]; 则系统将为字符数组str分配100个字节的内存单元,用于存放100个字符.而系统只为指针变量pc分 ...

  6. python中item是什么意思中文-Python中使用item()方法遍历字典的例子

    Python字典的遍历方法有好几种,其中一种是for...in,这个我就不说明,在Python了几乎随处都可见for...in.下面说的这种遍历方式是item()方法. item() item()方法 ...

  7. python中item是什么意思中文-Python中使用item()遍历字典

    Python中通常使用for...in遍历字典,本文使用item()方法遍历字典. item() item()方法把字典中每对key和value组成一个元组,并把这些元组放在列表中返回. DEMO 代 ...

  8. 微信小程序wx:for中的item什么意思以及wx:for-item的意思

    wx:for="{{list}}"用来循环数组,而list即为数组名wx:for-item="items" 即用来定义一个循环过程中每个元素的变量的 如果是一维 ...

  9. python for item in items_Python中items()系列函数的用法详解

    这篇文章主要介绍了Python中dictionary items()系列函数的用法,很实用的函数,需要的朋友可以参考下 本文实例讲述了Python中dictionary items()系列函数的用法, ...

最新文章

  1. 高通摄像头调试(OV8856)
  2. Maven 修改默认端口启动web项目
  3. 在网页中的flash游戏,按方向键浏览器的滚动条会跟着滚动
  4. java核心-多线程-Java多线程编程涉及到包、类
  5. 数据结构探险——线性表篇
  6. appnode php,环境软件路径参考
  7. OpenCV 使用光流法检测物体运动
  8. iphone中扫描wifi热点
  9. @符号的几种用法总结
  10. 如何获取微信应用appid
  11. Fixed Gear DIY整车配色 JavaScript版制作过程
  12. 陈强《高级计量经济学及stata应用》相关数据
  13. 張學友 - Private Corner 新专辑1.29
  14. 【Notepad++】Notepad++格式化JSON数据
  15. 基于Nginx实现访问控制,连接限制离
  16. 概率论复习题+部分详解
  17. 如何用键盘打开设备管理器里计算机的属性,技巧:在Windows10系统中使用键盘打开设备管理器的三种方法...
  18. trs java_TRS Java应用开发接口概述
  19. oracle通过UTL_SMTP包发送邮件
  20. 换一种思维方式之罗浩的《降级论》

热门文章

  1. 干净的Edge 初始页面
  2. android 升级ota 命令方式
  3. CoolShell-第2题
  4. 【机器学习】<刘建平Pinard老师博客学习记录>感知机原理
  5. 关于输电线路激光防外破在线监测装置
  6. onmouseenter和onmouseover的区别
  7. twitch 亚马逊云_如何为Twitch Prime Games下载Amazon Games App
  8. PCB材料选择与性能比较
  9. DSP芯片与仿真器上电顺序
  10. Zbar识别QRcode解读