首页 > 其他分享 >C语言的一些Hacking写法

C语言的一些Hacking写法

时间:2024-11-01 15:50:35浏览次数:4  
标签:bar GNU int 可以 C语言 printf Hacking 写法 表达式

很显然,这些写法大多并不规范,也不被提倡。
很显然,咱并没有在windows下试过这些代码,而且实测大部分在线编程网站用的是Linux,可以接受GNU C扩展支持。
如果有人问我为什么折腾,为什么以折腾这些无聊的东西作为目标,那他们完全可以问,为什么要登上最高峰?为什么人类要登月?………我选择去折腾,我,选择去折腾!(逃)

对int值进行位运算:

我们知道,int值以二进制存储。
于是可以用位运算来乘除2的次方数。

int i = 114514;
i <<= 1; //乘以2
printf("%d\n", i);
i >>= 1; //除以2
printf("%d\n", i);

>>=2会除以4,以此类推。

Bang-Bang折叠布尔值:

我们知道,判断条件只有两个值,0(false)和1(true)。
我们知道,当一个数字前面被加上!,它将变成一个判断条件。
我们还知道,双重否定表示极度的肯定(sodayo~)。
于是,在C语言中:

!!0 == 0
!!114514 == 1

没错,双叹号下只有两个值,0和1。
ACM的文章Catch-23: The New C Standard Sets the World on Fire中,通过这个可能并非规范中有定义但确实有效的例子严厉批判了C2x规范将realloc()内存为0设置为未定义行为而非free()内存的行为这一条,原因是realloc()做free()的写法和bang-bang一样在民间已经广为流传。

printf()中的三元表达式:

没错,至少GNU环境下,printf()中是可以套三元表达式的。
可以试下:

printf(1 ? "true\n" : "false\n");
printf(0 ? "true\n" : "false\n");

十分,甚至九分的优雅。

for()循环括号内执行代码:

C99放宽了对for()循环的限制。
于是就可以优(编)化(写)代(屎)码(山)。
init是一个表达式,但显然不做判断。
于是:
同时定义两个变量:

for(int i = 0 | int j = 255; ; )

condition就是一个判断,不过对于i--的情况,可以用上面的!!判断是否为0。

for (int i = 255; !!i; i--)

increment是一段代码,显然不会做任何限制

for (int i = 255; !!i; printf("%d\n", i--))
                ;

所以再稍微发挥一下:

for (int i = 255; !!i; printf((i % 2 == 0 ? "%d\n" : ""), i--))
                ;

非常离谱。

GNU C扩展:

表达式中的语句和声明:

在GNU C中,你可以用({})来获得一段表达式的值,这种表达式的值等于最后面的那个以;结尾的变量。
比如:

int foo = ({
        int bar = 1;
        bar++;
        bar;
});

于是foo变量的值等于最后那行语句bar;中bar的值。

__VA_ARGS__宏:

这应该是GNU C最出名的特性了吧。
可以让宏定义接受不定参数。
比如:

#define warning(...) fprintf(stderr, ##__VA_ARGS__)

三元表达式的缺省:

bar ?: foo等同于bar ? bar : foo
有什么用?
比如说:

fd >= 0 ?: exit(1);

可以让fd在open()失败时退出程序。
还是有点用的。

零长度数组:

char u[0];这样的写法是可以被接受的,一般放在结构体最后面,使结构体可以变长,普通程序基本用不到。不过在内存寸土寸金的年代,这样显然可以节省不少内存。

属性(attribute()宏):

attribute((constructor)):使函数在main()之前被执行。
attribute((destructor)):使函数在调用之后被执行。
attribute((unused)):函数或变量可能不会使用,可以作为注释用途或抑制编译警告。

后记:

(null)

标签:bar,GNU,int,可以,C语言,printf,Hacking,写法,表达式
From: https://www.cnblogs.com/Moe-hacker/p/18520415

相关文章

  • C语言中指针和数组的相互关系
    在C语言中,指针和数组有着紧密的相互关系。数组是数据的集合,而指针则是一个包含内存地址的变量。指针可以用来访问数组的元素,便于高效的内存访问和操作。更具体来说,数组名本身就是一个指向首元素的指针、通过指针运算,我们可以遍历数组的每个元素、数组和指针的索引操作是等价的、......
  • C语言数据结构之二叉树(BINARY TREE)链式存贮的简单实现
    C语言数据结构之二叉树(BINARYTREE)链式存贮的简单实现树型数据结构在应用中非常多,效率也非常好,只是结构相对复杂,理解起来有点儿难度!!!定义数据结构typedefstruct_BTreeNodeBTreeNode;struct_BTreeNode{intval;BTreeNode*lchild,*rchild;};自定义结构体数......
  • C语言用GNU源码编译建构系统工具(GNU BUILD SYSTEM)编译创建动态库
    C语言用GNU源码编译建构系统工具(GNUBUILDSYSTEM)编译创建动态库首先看一下这篇博文:C语言数据结构之顺序结构(Sequence)此次目的是将sequence.c改造一下,创建为一个动态链接库同时打包一个可发布的源码包,包括源码、头文件、测试文件!创建工作目录工作目录libmg(mg即muggles,一......
  • C语言数据结构之哈希表(HASHTABLE)的实现
    C语言数据结构之哈希表(HASHTABLE)的实现哈希表的每个节点保存的数据格式为key:value,其中key为字符串,根据字符串内容采用不同方法(哈希函数)生成一个无符号整型哈希码,根据表的长度,采用取余法,将数据存入表单元,如果此表单元中已存在数据,则以此表单元为链表头,向链表追加数据,这......
  • c语言经典20例(输入数组元素,进行排序并输出)
    下面是C语言程序的文字讲解,该程序实现了输入数组元素、对其进行选择排序并输出排序后的数组。#include<stdio.h>voidselectionSort(intarr[],intn){inti,j,min_idx,temp;//一次移动未排序部分的边界for(i=0;i<n-1;i++){//找到......
  • 使用C语言写一个猜数字游戏
    1:游戏的要求  1.电脑生成1~100的随机数  2.玩家猜数字,根据玩家输入的数字和产生的随机数的进行比较大了就反馈大了小了就反馈小      了,当两个数相等时候就反馈猜对了,且游戏结束2:制作一个菜单  我们在日常玩游戏的时候,都会先让我们选择玩什么模式呀,......
  • C语言复习总结超详细版(1)小白转身即变 有实例超级详细
    废话不多说直接开整注:本博文超级详细但是还是适合有C语言基础的观看 耗时很久,内容不会有问题但是 ⚠️字体晦涩望见谅引子第一个C语言程序#include<stdio.h>intmain(){printf("Hello,LJY!\n");return0;} main函数每个C语⾔程序不管有多少⾏代码......
  • 【PTA 编程题 7-3 】矩形运算 #C语言
    代码#include<stdio.h>#defineMAXM10#defineMAXN10intmain(void){intn;scanf("%d",&n);inta[MAXM][MAXN];for(inti=0;i<n;i++){for(intj=0;j<n;j++){scanf("%d",&a[i][j]);......
  • c语言自定义类型:枚举
    枚举类型的声明例如:  性别有:男生,女生  月份有:十二个月  三原色:也是可以一一列举以上这些数据类型的表示就可以使用枚举enumDay//星期{ Mon, Tue, Wed, Thur, Fri, Sat, Sun};enumSex//性别{ MALE, FMALE, SECRET};enumColor//颜......
  • c语言:动态内存管理中的malloc和free,calloc和realloc
    为什么要有动态内存分配?通过之前的学习,我们已经掌握的内存开辟方式有:inta=20;//在栈空间上开辟四个字节chararr[10]={0};//在栈空间上开辟10个字节的连续空间上述空间的开辟的大小是固定的数组在申明的时候,必须指定数组的长度,数组空间一旦确定了大小不能进行调整。......