C语言中:
extern :extern(外部引用)可以置于变量或者函数前,以标示变量或函数的定义在别的文件中,在一个文件中用到的extern这些变量或函数是外来的,不是本文件定义的,提示编译器遇到此变量和函数时在其他模块中寻找其定义。注意,只有其他文件中的全局变量才能被其他文件所extern。
extern int val;
注:
此处的函数类型可以省略,即extern val;
因为extern的作用就是告诉编译器这个变量是在其他文件中定义的(是外援)。编译器是相信自己人的,所以在编译的时候要是看到val变量时会认为它是存在,不会报错。只有在链接的时候链接器才会去其它obj文件中寻找val变量的定义(地址),找到则顺利链接,否则报错。因为编译器只需要知道extern所声明变量的名字就可以了,所以extern int val 可以写成 extern val(即省略变量类型)。
至于 extern“C”的用法, 一般认为属于 C++的范畴。extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,但在C++中为了兼容面向过程语言(C),扩展了extern功能。
static : 在C中,static(静态的) ......
综述
看一下输入操作的原理,
程序的输入都建有一个缓冲区,即输入缓冲区。一次输入过程是这样的,当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin等输入输出函数直接从输
入缓冲区中取数据。正因为cin等输入输出函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求
键盘输入。
---------------
第一:
要注意不同的函数是否接受空格符、是否舍弃最后的回车符的问题!
读取字符时:
scanf()以Space空格、Enter、Tab结束一次输入,不会舍弃最后的回车符(即回车符会残留在缓冲区中),(区别读字符串时会清楚)//所以可以用getchar()清除;
getchar()以Enter结束输入,也不会舍弃最后的回车符;
读取字符串时:
scanf()以Space、Enter、Tab结束一次输入,会舍弃最后的回车符(区别读字符时)和所有的空格等等。
gets()以Enter结束输入(空格不结束),接受空格,会舍弃最后的回车符!
第二:为了避免出现上述问题,必须要清空缓冲区的残留数据,可以用以下的方法解决:
方法1:C语言里提供了函数清空缓冲区,只要在读数据之前先清空缓冲区就没问题了!
& ......
extern "C"包含双重含义,其一:被它修饰的目标是“extern”的;其二:被它修饰的目标是“C”的。
1)被extern “C”限定的函数或变量是extern类型的;
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其他模块中使用。
注意:extern int a;
仅仅是在声明一个变量,并不是定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
通常,在模块的头文件中对模块提供给其他模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错,它会在连接阶段中从模块A编译生成的目标代码中找到此函数。
与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern "C"修饰 ......
一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。程序结束时由编译器自动释放。
2、堆区(heap) — 在内存开辟另一块存储区域。一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—编译器编译时即分配内存。全局变量和静态变量的存储是放在一块的,初始化的 全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
例子程序
这是一个前辈写的,非常详细
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b;// 栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //"123456\0"在常量区,p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10); ......
一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。程序结束时由编译器自动释放。
2、堆区(heap) — 在内存开辟另一块存储区域。一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—编译器编译时即分配内存。全局变量和静态变量的存储是放在一块的,初始化的 全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。
例子程序
这是一个前辈写的,非常详细
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b;// 栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //"123456\0"在常量区,p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10); ......
ubuntu下的c/c++环境搭建是比较简单,因为有apt和新立得的帮助.
1.
首先是配置gcc,在ubuntu安装完成已经有gcc了(gcc是由GNU之父Stallman所开发的linux下的编译器,全称为GNU
Compiler Collection, 目前可以编译的语言包括:C, C++, Objective-C, Fortran, Java,
and
Ada.).但是gcc还不能编译文件.因为缺少一些头文件.那么我们就要来配置这些头文件.在这里我们需要安装build-essential这个软件
包,安装了这个包会自动安装上g++,libc6-dev,linux-libc-dev,libstdc++6-4.1-dev等一些必须的软件和头文
件的库.
安装build-essential,你可以在新立得搜索然后安装或者在终端里输入:
sudo apt-get install build-essential
2.
除了编译器外,我们还需要一个文本编辑器.因为我们需要编辑c程序的代码.其实ubuntu有自带编辑器,我们可以创建一个文档.然后输入代码,讲名字改为*.c. 还可以使用另外一个文本编辑器vi. 如果你的ubuntu没有.那我们可以在终端输入:
sudo apt-get install vim-full
完成后我们就有一个非常强大的编辑器vi.
3.
完成以上两步,你就可以开始编译你ubuntu上第一个c语言程序.
在主文件夹中,建立一个hello.c的文件,双击文件输入代码:
#include <stdi ......
ubuntu下的c/c++环境搭建是比较简单,因为有apt和新立得的帮助.
1.
首先是配置gcc,在ubuntu安装完成已经有gcc了(gcc是由GNU之父Stallman所开发的linux下的编译器,全称为GNU
Compiler Collection, 目前可以编译的语言包括:C, C++, Objective-C, Fortran, Java,
and
Ada.).但是gcc还不能编译文件.因为缺少一些头文件.那么我们就要来配置这些头文件.在这里我们需要安装build-essential这个软件
包,安装了这个包会自动安装上g++,libc6-dev,linux-libc-dev,libstdc++6-4.1-dev等一些必须的软件和头文
件的库.
安装build-essential,你可以在新立得搜索然后安装或者在终端里输入:
sudo apt-get install build-essential
2.
除了编译器外,我们还需要一个文本编辑器.因为我们需要编辑c程序的代码.其实ubuntu有自带编辑器,我们可以创建一个文档.然后输入代码,讲名字改为*.c. 还可以使用另外一个文本编辑器vi. 如果你的ubuntu没有.那我们可以在终端输入:
sudo apt-get install vim-full
完成后我们就有一个非常强大的编辑器vi.
3.
完成以上两步,你就可以开始编译你ubuntu上第一个c语言程序.
在主文件夹中,建立一个hello.c的文件,双击文件输入代码:
#include <stdi ......
一个C语言运行库大致包含了如下功能:
1. 启动与退出: 包括入口函数及入口函数所依赖的其它函数等
2. 标准函数: 由C语言标准规定的C语言标准库所拥有的函数实现.
3. I/O: IO功能的封装和实现
4. 堆:堆的封装和实现
5. 语言实现: 语言中一些特殊功能的实现.
6. 调试: 实现调试功能的代码.
在这些运行库的组成成分中, C语言标准占据了主要并且大有来头.
1. 变长参数
函数的实现如下:
#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
//va_start取第一个参数的地址, 并在栈上向上移动指针
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
//va_arg主要是先移动指针,再取上一个值.
//注意: t是指要传入的类型,应为要确定移动的指针的远近.
#define _crt_va_end(ap) ( ap = (va_list)0 )
//使ap指针为0
//主要是利用栈的原理.
#include <stdio.h>
#include <stdarg.h>
int sum(int a, ...)
{
int v = 0;
va_list ap;
va_start(ap, a);
while(a--)
v += va_arg(ap, int);
va_end(ap);
return v;
}
int main()
{
printf("%d", sum(9, 1,2,3,4,5,6,7,8 ......
一个C语言运行库大致包含了如下功能:
1. 启动与退出: 包括入口函数及入口函数所依赖的其它函数等
2. 标准函数: 由C语言标准规定的C语言标准库所拥有的函数实现.
3. I/O: IO功能的封装和实现
4. 堆:堆的封装和实现
5. 语言实现: 语言中一些特殊功能的实现.
6. 调试: 实现调试功能的代码.
在这些运行库的组成成分中, C语言标准占据了主要并且大有来头.
1. 变长参数
函数的实现如下:
#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
//va_start取第一个参数的地址, 并在栈上向上移动指针
#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
//va_arg主要是先移动指针,再取上一个值.
//注意: t是指要传入的类型,应为要确定移动的指针的远近.
#define _crt_va_end(ap) ( ap = (va_list)0 )
//使ap指针为0
//主要是利用栈的原理.
#include <stdio.h>
#include <stdarg.h>
int sum(int a, ...)
{
int v = 0;
va_list ap;
va_start(ap, a);
while(a--)
v += va_arg(ap, int);
va_end(ap);
return v;
}
int main()
{
printf("%d", sum(9, 1,2,3,4,5,6,7,8 ......