代码改变世界

随笔分类 - C

printf 中转义字符大全

2016-06-06 14:32 by youxin, 1343 阅读, 收藏, 编辑
摘要: printf 中转义字符大全 阅读全文

2的m次方 内存对齐

2016-01-26 18:09 by youxin, 1524 阅读, 收藏, 编辑
摘要: 在存储的时候,为了提高效率,一般都会让偏移量落在2的m次方的位置上,而且常有向上取整和向下取整两种需求。向下取整PALIGN_DOWN(x,align) (x & (- align))这样做为什么可以,因为align 取反 还是自己,只是高位全变成1了,然后再和原来的数&运算,此时不对齐多出来的1都... 阅读全文

C语言 ## __VA_ARGS__ 宏

2015-10-19 18:24 by youxin, 717 阅读, 收藏, 编辑
摘要: 在GNU C中,宏可以接受可变数目的参数,就象函数一样,例如:12#define pr_debug(fmt,arg...) \ printk(KERN_DEBUG fmt, ##arg)用可变参数宏(variadic macros)传递可变参数表你可能很熟悉在函数中使用可变参数表,如:1voidpr... 阅读全文

#ifdef和#if defined的差别

2015-10-13 18:02 by youxin, 4566 阅读, 收藏, 编辑
摘要: 注意两者都有个define的作用,区别在于使用方式上。前者的通常用法是:#ifdef XXX ....#else ....#endif 只能在两者中选择是否有定义。对于后者,常用法是:#if defined xxx1 ....#elif defined xxx2 ....#elif define... 阅读全文

零长度数组的妙用

2015-08-09 21:42 by youxin, 1025 阅读, 收藏, 编辑
摘要: 零长度是指定义数组时,指定其长度为0(如int arr[0];),这样的数组不占用实际的空间,但能通过数组名访问到其指向的地址。如下例所示:#include #include struct device{ int num; int count; int reserve[0]; /*... 阅读全文

C语言高级宏技巧

2015-03-02 21:05 by youxin, 1853 阅读, 收藏, 编辑
摘要: 特殊符号#、##(1)# Whenyouputa#beforeanargumentinapreprocessor macro,thepreprocessorturnsthatargumentintoacharacterarray. 在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数... 阅读全文

转:zero length array问题

2015-02-28 13:49 by youxin, 739 阅读, 收藏, 编辑
摘要: 单看这文章的标题,你可能会觉得好像没什么意思。你先别下这个结论,相信这篇文章会对你理解C语言有帮助。这篇文章产生的背景是在微博上,看到@Laruence同学出了一个关于C语言的题,微博链接。微博截图如下。我觉得好多人对这段代码的理解还不够深入,所以写下了这篇文章。为了方便你把代码copy过去编译和调... 阅读全文

求1+2+…+n,要求不能使用乘除法、for、while、if、else、s witch、case 等关键字以及条件判断语句(A?B:C)和不用循环/goto/递归输出1~100的10种写法

2014-11-14 20:36 by youxin, 2030 阅读, 收藏, 编辑
摘要: 来源:据说是某一年某个公司的面试题题目:求1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A?B:C)分析:这题本来很简单,但是不能用循环和条件判断语句。但是理论上所有的递归都可以转化为循环,那是否可以用递归代替循环呢?照着这个... 阅读全文

setjmp/longjmp 使用

2014-03-25 21:10 by youxin, 645 阅读, 收藏, 编辑
摘要: C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转(通常情况下,很多人都建议不要使用goto语句,因为采用goto语句后,代码维护工作量加大)。另外,C语言标准中还提供一种非局部跳转“no-local goto",其通过标准库中的两个标准函数setjmp和longjmp来实现。C标准库下面是K&R的《C程序设计语言(第2版.新版)》第232页给出的关于标准库的说明。非局部跳转头文件中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别的,它允许立即从一个多层嵌套的函数调用中返回。8.1 setjmp#include int setjmp(jmp_buf env);s 阅读全文

C 语言的可变参数表函数的设计

2013-11-08 23:23 by youxin, 798 阅读, 收藏, 编辑
摘要: 在c语言中使用变长参数最常见的就是下面两个函数了: 那他们是怎样实现支持变成参数的呢?在使用变长参数的函数(这里假设是func)实现部分其实用到了stdarg.h里面的多个宏来访问那些不确定的参数,它们分别是: 假设lastarg是func的最后一个具名参数,即在func函数定义中...之前的那个参 阅读全文

转:一个strcpy的问题(很容易做错)

2013-09-28 02:26 by youxin, 770 阅读, 收藏, 编辑
摘要: 下面的执行结果是什么?#include#includevoid main(){char s[]="123456789";char d[]="123";strcpy(d,s);printf("d=%s,\ns=%s",d,s);}执行结果:d=56789, s=123456789书上有关于这个的解答,说是因为当初分配的内存地址是连续内存的问题,原来的是1234\0123456789\0,strcpy后变成123456789\06789\0。分析:首先要解释一下,char s[]="123456789"; char d 阅读全文

判断栈和堆的生长方向

2013-09-10 20:36 by youxin, 6987 阅读, 收藏, 编辑
摘要: 如何判断栈的增长方向?对于一个用惯了i386系列机器的人来说,这似乎是一个无聊的问题,因为栈就是从高地址向低地址增长。不过,显然这不是这个问题的目的,既然把这个问题拿出来,问的就不只是i386系列的机器,跨硬件平台是这个问题的首先要考虑到的因素。在一个物质极大丰富的年代,除非无路可退,否则我们坚决不会使用汇编去解决问题,而对于这种有系统编程味道的问题,C是一个不错的选择。那接下来的问题就是如何用C去解决这个问题。C在哪里会用到栈呢?稍微了解一点C的人都会立刻给出答案,没错,函数。我们知道,局部变量都存在于栈之中。似乎这个问题立刻就得到了解答,用一个函数声明两个局部变量,然后比较两个变量的地址, 阅读全文

float 浮点数与零值0比较大小

2013-09-06 20:29 by youxin, 42946 阅读, 收藏, 编辑
摘要: float x;千万不要写x==0;写出float x 与“零值”比较的if语句——一道面试题分析写出float x 与“零值”比较的if语句请写出 floatx 与“零值”比较的 if 语句:const float EPSINON = 0.00001;if ((x >= - EPSINON) && (x =”或“=”或“=-EPSINON) && (x#include main(){ float d1, d2, d3, d4; d1 = 194268.02; d2 = 194268; d4 = 0.02; d3 = d1 - d2; if (d3 > 阅读全文

C的memset,memcpy,strcpy 的区别 及memset memcpy memmove源码

2013-08-20 20:52 by youxin, 1137 阅读, 收藏, 编辑
摘要: extern void *memcpy(void *dest,void *src,unsigned int count);#include 功能:由src所指内存区域复制count个字符串到dest所指内存区域. 说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针. memse... 阅读全文

转:一道笔试题-将int型数组强制转换为char*,再求strlen,涉及大小端

2013-08-11 15:14 by youxin, 404 阅读, 收藏, 编辑
摘要: 写出如下程序运行结果:#include#includeintmain(){inta[2000];char*p=(char*)a;for(inti=0;i int check() { union check { int i; char ch; }c; printf("%d\n" , &c.i); printf("%d\n", &c.ch); c.i =1; return (c.ch == 1); } int main() { int ret; ret = ch... 阅读全文

C语言中 移位操作运算

2013-08-04 14:50 by youxin, 1128 阅读, 收藏, 编辑
摘要: 移位规律:左移时总是移位和补零。右移时无符号数是移位和补零,此时称为逻辑右移;而有符号数大多数情况下是移位后补最左边的位(也就是补最高有效位),移几位就补几位,此时称为算术右移。(其实跟扩展逻辑一样)。C语言中的移位操作,内容不多。不过有些地方你不注意,就疏忽了。先做两个小题先。(1)unsigned char x=3;x>1是多少?(2)char x=3;x>1是多少?(3)char x=-3;x>1是多少?3写成二进制数是00000011;-3写成二进制数是(补码)11111101。程序执行的时候,操作的是数值的编码表示,也就是数值在内存中的二进制表示。比如说,程序取-3 阅读全文

有符号和无符号数回绕问题(补码加法和补码减法)

2013-08-04 02:22 by youxin, 2381 阅读, 收藏, 编辑
摘要: 我们知道,在有符号数中,最小值-1=最大值,最大值-1=最小值。我们称之为回绕wrap around。现在来说一般建议避免,因为其他架构的CPU,发生整数溢出时可能会触发CPU异常。无符号最大值+1=0.可见,无符号和有符号都会回绕。为什么最小值-1=最大值。这要从计算机内部数字表示形式开始,都是采用补码表示。补码表示有一些好处,统一了0([0]补=0000;).把减法都可以转换为加法。补码加法:[x]补+[y]补=[x+y]补 (mod 2^(n+1))(证明略)。例:x=+1011;y=-0101;求x+y;解:[x]补=01011;[y】补=11011;[x]补 0... 阅读全文

数组名和指针区别(还有数组退化等)

2013-08-04 01:42 by youxin, 1668 阅读, 收藏, 编辑
摘要: 以前一直认为数组名和指针99%是相似的,只不过表达形式不同而已。但现在遇到越来越多的程序表面他们有所不同。如在数组初始话时:char d[5];d="hell"; //不能直接赋值,只能一个个赋值错误。vs2010提示表达式d必须是可修改的左值。但是如果是指针char *d;d="hell"; //字符串常量后面会自动添加\0.则可以。还有其他区别,如1、地址相同,大小不同看下面代码:1intarr[10];2int*p=arr;3cout main() { int i; float X[MAX]; for (i = 0; i main() ... 阅读全文

无法从“const char *”转换为“char *”

2013-08-04 00:35 by youxin, 5459 阅读, 收藏, 编辑
摘要: 写了如下的一段代码:const char *str; char *p=str;提示错误:const char* 不能用于初始化char *类型的实体。这是为什么?我想应该是const char *要求比较严格,赋给一个要求低的不行(如果p更改了内容就后患无穷了),所以禁止了直接赋值。指向const的指针不能被赋给指向非const的指针,所以应该用strcpy,也就是另开一块内存,把字符一个个复制过去const char *expr = "goodidea";char *buf = new char[strlen(expr)+1];strcpy(buf, expr);strc 阅读全文

c语言数组初始化问题

2013-08-04 00:25 by youxin, 5432 阅读, 收藏, 编辑
摘要: 2147483648字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素。charstr[10]={'I','','a','m','',‘h’,'a','p','p','y'};即把10个字符分别赋给str[0]到str[9]10个元素如果花括号中提供的字符个数大于数组长度,则按语法错误处理;若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即'\0')。如char str[10] = {'\ 阅读全文