转载:http://hi.baidu.com/shanghaocool/blog/item/e15f8797021cf81a7bf480b2.html
完成内容:
1.收获备忘;
2.局部变量、全局变量、静态局部变量、静态全局变量的异同;
3.设计函数atoi()(字符串转int型)
4.含参数的宏与函数的优缺点;
一.收获备忘
1.数组名指向的是一块内存块,内存的地址与大小在生命期内不可改变,只有内存块中的内容可以改变;指针可以随时指向任意类型的内存块;
2.strcpy()函数的原型:char
*strcpy(char *strDestination, const char *strSource);
malloc()函数的原型:void
*malloc(size_t size);
free()函数的原型:void
free(void *memblock);
3.指针在free()或delete后,需重新指向NULL,或指向合法的内存;
4.申请动态内存后,应该马上判断是否申请成功(malloc和new申请动态内存不成功返回NULL),若申请不成功,则用exit(1)强制退出程序;
5.内存分配的三种方式:
(1).从静态存储区域分配:变量在编译时已经分配好,在整个程序运行期间都存在,例如:全局变量,静态全局变量;
(2).从“栈”上分配:函数内的局部变量,在使用时自动从栈上创建内存区域,函数结束时自动释放。由于栈上内存的分配运算内置于处理器的指令集中,使用效率很高,但容量有限;
(3).从“堆”上分配:即动态内存分配,程序员可使用malloc
()/new申请任意大小的动态内存空间,同时由程序员决定何时使用free ()/delete去释放已申请的内存。使用起来十分灵活,但最容易出问题;
6.指针参数传递内存的方法及常见错误P47-P49
二.局部变量,全局变量,静态局部变量,静态全局变量的异同
虽然之前在编程时对这四个“变量”就有不少困惑,但一直没去细究,前两天在联想的笔试题中看到了这样一道题,貌似知道它们的区别却又不能说出其中的原理,今天决定将其弄清楚。
局部变量:在一个函数中或复合语句中定义的变量,在动态存储区分配存储单元,在调用时动态分配,在函数或复合语句结束时自动释放;
静态局部变量:在一个函数中定义局部变量时,若加上static声明,则此变量为静态局部变量,在静态存储区分配存储单元,在程序运行期间都不释放;静态局部变量只能在该函数中使用;静态局部变量在编译时赋值(若在定义时未进行赋值处理,则默认赋值为0(对数值型变量)或空字符(对字符型变量));静态局部变量在函数调用结束后不自动释放,保留函数调用结束后的值;
全局变量:在函数外定义的变量称为全局变量;全局变量在静态存储区分配存储单元,在程序运行期间都不释放,在文件中的函数均可调用该全局变量,其他文件内的函数调用全局变量,需加extern声明;
静态全局变量:在函数外定义变量时,若加上static声明,则此变量为静态全局变量;静态全局变量在静态存储区分配存储单元,在程序运行期间都不释放,静态全局变量在编译时赋值(若在定义时未进行赋值处理,则默认赋值为0(对数值型变量)或空字符(对字符型变量));只能在当前文件中使用;
参考谭浩强的《C程序设计第二版》P180,可从三个方面对以上四种变量进行区分:
1.从作用域角度分,有局部变量和全局变量:
局部变量
自动变量(auto变量,函数结束后释放)
静态局部变量(函数结束后值保留)
全局变量
静态外部变量(只限本文件中使用)
外部变量(允许其他文件引用)
2.从变量的生存期分,有动态存储和静态存储两种,动态存储即在调用函数时临时分配单元,静态存储则是程序整个运行时间内都存在。
动态存储
形式参数(本函数内有效)
auto自动变量(本函数内有效)
register寄存器变量(本函数有效)
静态存储
静态局部变量(本函数内有效)
静态外部变量(本文件中有效)
外部变量(允许其他文件引用)
3.从变量的储存位置分
内存中静态存储区
静态局部变量
静态外部变量
外部变量
内存中动态存储区
auto自动变量和形式参数
CPU中的寄存器
寄存器变量
三.设计函数int
*atoi(const char *str);
在联想的笔试题中看到这个题目,特意拿来练练手;
程序代码如下:
#include <stdio.h>
#include <assert.h>//使用断言
#include <ctype.h>//使用isspace()、isdigit()函数的头文件
#include <math.h>
#define INT_MAX (int)((pow(2, sizeof(int) * 8)) / 2.0 - 1)
#include <stdio.h>
#include <assert.h>//使用断言
#include <ctype.h>//使用isspace()、isdigit()函数的头文件
#include <math.h>
#define INT_MAX (int)((pow(2, sizeof(int) * 8)) / 2.0 - 1)
int myatoi(const char *string)
{
int flag = 1;
int result = 0;
assert(string != NULL);//若string指向NULL,则判断非法调用myatoi()函数
//若字符串有空格或制表符,则跳过;
while (isspace(*string))
{
string++;
}
//获取字符串的'+','-'符号位;
if (*string=='+' || *string=='-')
{
flag = (*string == '-') ? -1 : 1;
string++;
}
//程序到这里,已经没有空格和'+','-'号了,若接下来的字符是数字,
//则计算出数字的大小,若不是数字,则不计算,result依旧为0;
while (*string!='\0' && isdigit(*string))
{
result = 10 * result + (*string++ - '0');
}
//判断最后结果是否溢出,若溢出则退出程序
if ((unsigned)result > INT_MAX)
{
printf("The Number Input is larger than INT_MAX:%d\n",
INT_MAX);
printf("exit!\n");
exit(1);
}
return (result * flag);
}
int main(void)
{
printf("%d\n", myatoi("+1234"));
printf("%d\n", myatoi("-2147483647"));
printf("%d\n", myatoi("1234"));
printf("%d\n", myatoi("adf 1234"));
}
此函数中
1.首先通过断言assert判断对myatoi()的调用是否合法;
2.判断字符串开头是否有空格或制表符(TAB),有则跳过;
3.若字符串第一个有效字符为’-‘,则flag置-1,若为’+’,则flag置1,若为其他字符,则判断此字符串为非数字字符串,result的最终值为0;
4.将字符类型的数字转换成int类型的数字,
5.判断result是否越界,若越界,跳出程序,否则返回result*flag的值;
这道题主要考的是程序员的编程风格,虽说这个函数看上去很简单,但如果要考虑到程序的健壮性,正确定,可靠性,效率,易用性,可扩展性,可移植性等属性的话,程序编写起来就不简单了;
四.含参数的宏与函数的优缺点
无参的宏就用得多了,但带参数的宏呢?见过很多,但真正自己去编的几乎没有,今天,顺带把这个问题也搞清楚。
含参数的宏优点:
省去了函数调用的开销,运行效率高.
含参数的缺点:
由于宏本质上是字符串的替换,所有可能会由于一些参数的副作用导致得出
错误的结果.
如:
#define max(a, b)( ((a) > (b)) ? (a) : (b) )
如果程序中出现这样的调用: max(a++, b);
将导致a被计算2次,从而可能得到错误的结果,而函数调用不会出现这种问题.
另外,如果程序中有多次宏替换的话,可能导致代码体积变大.
函数调用的优点:
没有带参数宏可能导致的副作用,计算的正确性较宏更有保证.
函数调用的缺点:
函数调用需要一些参数,返回地址等入栈,出栈的开销,效率没有带参数的宏高.
分享到:
相关推荐
- 当设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需考虑重入问题。 - 为了创建可重入的函数,应避免在函数中使用`static`变量。 - **特殊用途**: - 当函数返回值为指针类型时,通常使用...
- **全局变量**:存储在静态数据区,即使函数调用结束,其值仍然保留。 - **局部变量**:存储在栈中,随着函数调用的开始而创建,函数调用结束时自动销毁。 ### 平衡二叉树的概念 平衡二叉树是一种特殊的二叉搜索...
未解决的问题包括全局变量的内存分配时间、静态变量和全局变量的区别、内存对齐的原理、浮点数的存储和运算、`lea`指令的作用、`tlink`的工作过程、`double`类型的具体存储方式、结构体的传递和返回机制,以及空指针...
2. 局部变量、静态变量、全局变量: - 局部变量:在方法内部定义,随着方法调用结束而释放。 - 静态变量:属于类级别,生命周期与类相同,不随对象创建和销毁而改变。 - 全局变量:在类的外部定义,随着程序运行...
2. 全局变量和局部变量的区别:全局变量储存在静态数据区,局部变量在堆栈。 3. 平衡二叉树:平衡二叉树是一种特殊的二叉树,左右子树都是平衡二叉树且左右子树的深度差值的绝对值不大于 1。 4. 堆栈溢出:堆栈溢出...
1. 静态库和动态库的异同 静态库(Static Library)和动态库(Dynamic Library)是两种不同的库类型。静态库是在编译时将库文件编译成目标文件,然后链接到可执行文件中。动态库是在运行时加载到内存中的。静态库的...
8.8 局部变量和全局变量 112 8.8.1 局部变量 113 8.8.2 全局变量 119 8.9 变量的存储类别 120 78.9.1 动态存储方式与静态动态存储方式 120 8.9.2 auto变量 120 8.9.3 用static 声明局部变量 121 8.9.4 register 变量...
8.8 局部变量和全局变量 112 8.8.1 局部变量 113 8.8.2 全局变量 119 8.9 变量的存储类别 120 78.9.1 动态存储方式与静态动态存储方式 120 8.9.2 auto变量 120 8.9.3 用static 声明局部变量 121 8.9.4 register 变量...
1. 静态存储区域分配:这部分内存主要包含全局变量和静态变量,它们在程序开始执行时分配,并在整个程序运行期间持续存在。 2. 栈上创建:函数内部的局部变量通常在栈上分配,当函数执行完毕,这些变量的内存会被...
然而,由于`$bar`在函数内部被声明为局部变量,其改变不会影响到全局的`$bar`,这就是变量作用域的概念。 在PHP中,变量的作用域决定了变量在代码的哪些部分是可见的。通常有四种作用域: 1. 全局(global):在...
资料中涵盖了函数的定义和使用、参数传递、返回值以及局部变量和全局变量的区分。 数据类型: C++的数据类型比C语言更为丰富,提供了布尔型变量、双字节宽字符类型wchar_t等。资料详细解释了基本数据类型的扩充、...
- 讨论静态局部变量和静态外部变量的特性和用法。 - 解释静态存储期的概念。 7. **寄存器变量(4.7)** - 介绍寄存器变量的特点。 - 探讨其在提高程序性能方面的作用。 8. **块结构(4.8)** - 说明复合...
- 讨论变量的作用域,如局部变量和全局变量,以及静态变量的特性。 - 了解内联函数、默认参数函数和函数模板的概念。 5. **数组** - 熟悉一维数组和二维数组的声明、初始化以及数组元素的访问。 - 理解数组名...
- **静态变量**:解释静态局部变量与静态外部变量的特性。 - **寄存器变量**:探讨寄存器变量的概念及其使用限制。 - **块结构**:说明函数体与复合语句之间的关系。 - **初始化**:介绍变量与数组的不同初始化...
9. **函数**:深入讲解函数的使用,包括函数的声明、定义、参数传递、返回值、局部变量和全局变量的概念。 10. **数据类型**:详细介绍C++中的各种数据类型,如布尔型(bool)、字符型(char)、双字节型(wchar_t...
此外,JavaScript的变量作用域和内存管理也有其独特之处,比如全局变量和局部变量的区别,以及垃圾回收机制。理解这些概念对于编写高效且无错的JavaScript代码至关重要。虽然这个PPT可能更适合初学者,但深入学习...
### Java面试测试题目知识点...- Java中使用静态变量来模拟全局变量的行为,避免全局变量可能导致的问题。 #### 57. 如何将String类型转化成Number类型 - 使用`Integer.parseInt()`、`Double.parseDouble()`等方法。
纯代码函数不包含任何副作用,如修改全局变量或调用其他可能改变状态的函数,因此它们是可重入的。 (二) 使用了局部静态变量的函数,是不可重入的 局部静态变量在函数调用结束后不会被销毁,因此如果多个线程同时...