博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
每日一题(十)
阅读量:3950 次
发布时间:2019-05-24

本文共 2629 字,大约阅读时间需要 8 分钟。

文章目录

10.11 函数形参问题

分析如下程序的输出:

void fun(int m, int n){
printf("m = %d, n = %d\n", m, n);}int main(void){
int k = 3; fun(k += 3, ++k); printf("k = %d", k); return 0;}

主要考察是调用函数的时候参数的入栈顺序以及变量的运算,参数入栈顺序一般是从右到左,所以先执行++k,将4传给n;再执行k += 3将7的值传给m。注意这里是k做运算之后才传入的函数,所以k += 3, ++k并不是在调用函数的栈中执行的,所以k的值是保存下来的,所以最终输出为:

m = 7, n = 4

k = 7

这种方式和编译器中得函数调用关系相关即先后入栈顺序。不过不同编译器得处理不同。也是因为 C 标准中对这种方式说明为未定义,所以各个编译器厂商都有自己得理解,所以最后产生得结果完全不同。因为这样,所以遇见这种函数,我们首先要考虑我们得编译器会如何处理这样得函数,其次看函数得调用方式,不同得调用方式,可能产生不同得结果。最后是看编译器优化。

10.12 二级指针偏移

分析下面程序:

#include 
void fun(int b[][3]){
++b; b[1][1] = 120;}int main(void){
int a[][3] = {
{
1, 2, 3}, {
4, 5, 6}, {
7, 8, 9} }; fun(a); printf("a[2][1] = %d\n", a[2][1]); return 0;}

首先要了解数组传入函数后的变化**:我们知道数组传入函数的时候,会转换为指针,但是对于二维数组,只转换一次**,即int b[][3]传入函数的时候是以

int (*b)[3]的形式,即一个指向数组的指针,数组中有三个元素。所以传入a后,相当于b = a[0]

++b代表指针b移动一个步长的位置,这里b指向一个三个元素的int型数组,所以++b之后b = a[1][]

指向b[1][1] = 120, 其中b[1][1]相当于*(*(b+1)+1),相当于指针b偏移了一个步长之后又偏移了一个元素的位置,用a表示a[1+1][0+1]a[2][1] = 120,所以printf输出的就是120。

10.13 #ifdef与#if define 的区别

用一段程序说明:

#include 
#define A#define Bvoid test(int a,int b){
}int main(void){
#if 0 #ifdef A&&B test(printf("a\n"),printf("b\n"));#endif#endif#if defined(A)&&defined(B) test(printf("a\n"),printf("b\n"));#endif return 0;}

如果是#if defined(A)&&defined(B)的形式,输出:

b

a

如果是#ifdef A&&B的形式,会提示:

image-20201017102017535

因为#ifdef虽然我们最常见也用得最多,可是#if defined(XXX)却可以有 &&,||,!,逻辑与,逻辑或,逻辑非等操作,而#ifdef却不支持这样的特性。

10.14指针实现交换数据时的溢出情况

程序如下:

void swap(int *a, int *b){
*a = *a + *b; *b = *a - *b; *a = *a - *b;}

请问上述程序可否实现两个int数据的交换?看起来没毛病,可是容易忽略一个问题,那就是int是有符号数据的溢出!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nwq6O0su-1602905143136)(…/…/…/%E8%BD%AF%E4%BB%B6%E7%AE%A1%E5%AE%B6/Typora/%E5%9B%BE%E7%89%87%E5%BA%93/image-20201017103737242.png)]

**只有当a、b同符号的时候才可能发送溢出!!!**因为这里有加减操作,所以当两个同符号的数据相加的时候就有可能溢出。

比如:

交换-5, -7。 以4bit为例。

-5 = 1011 (补码) -7 = 1001 (补码)

(-5)+ (-7)= 10100=0100=4 (溢出后为4)

4-(-7)= 4 +7=0100 + 0111 = 1011 = -5的补码

4-(-5)= 4 + 5 = 0100 + 0101 = 1001 = -7的补码

注意,函数是在第一步的时候可能溢出,但是后面的操作是基于溢出的数据的,而且后面又可以把溢出的部分减回来,所以这里虽然可能会发送溢出,但是仍然可以得到正确的数据。

10.15 三目运算的数据转换

程序如下:

#include 
void test(){
printf("int: %d\n", sizeof(int)); printf("double: %d\n", sizeof(double)); printf("test1: %d\n", sizeof(100 < 1 ? 0.1 : 1)); printf("test2: %d\n", sizeof(100 > 1 ? 0.1 : 1));}int main(void){
test(); return 0;}

输出结果为:

int:    4double: 8test1: 8test2: 8

如果按照我们分析,(100 < 1 ? 0.1 : 1)输出的会是1,也就是int型数据,但是实际上被转换为double类型了。

实际上三目运算最后输出的是一个变量,在一个表达式中,数据格式要统一,所以在得出运算之前就将所有变量转换为同一种数据格式了。

转载地址:http://ytwzi.baihongyu.com/

你可能感兴趣的文章
OCILIB VC2008 效率测试
查看>>
PL/SQL设置NUMBER显示为字符串
查看>>
linux ftp 脚本 -- 使用程序执行脚本
查看>>
MFC CListBox的使用
查看>>
VS2008向MFC 对话框 添加托盘图标(显示和消失)
查看>>
redhat中vsftp开机自启动
查看>>
MySQL存储过程,生成大量数据
查看>>
查询字段值出现多次的字段值
查看>>
SQL Server表存在则进行查重 SQL语句
查看>>
redhat 9 下sqlite 3的安装及编程
查看>>
两个同步表的字段复制.Oracle.
查看>>
windows MySQL 报“Got a packet bigger than 'max_allowed_packet' bytes”错误,解决过程.
查看>>
在Redhat9下静态编译glib库.
查看>>
CImg库编译使用.
查看>>
SQL Server循环执行动态SQL语句.
查看>>
ubuntu10.4网卡名由eth0改为eth4,导致获得不了IP地址.解决方法.
查看>>
CheckPoint关键词做字段名使用.
查看>>
Qt QSplitte分割器使用(用户手动改变窗口大小)
查看>>
Qt动态加载动态库
查看>>
java8新特性
查看>>