小编Vil*_*ray的帖子

异或的关联性质的逻辑证明

我遇到了一个常见的编程访谈问题:给定一个无符号整数列表,找到一个在列表中出现奇数次的整数.例如,如果给出列表:

{2,3,5,2,5,5,3}
Run Code Online (Sandbox Code Playgroud)

解决方案将是整数5,因为它在列表中出现3次而其他整数出现偶数次.

我的原始解决方案包括设置一个排序数组,然后迭代数组:对于每个奇数元素,我会添加整数,而对于每个偶数元素,我会减去; 结束总和是解决方案,因为其他整数将取消.

但是,我发现只需在每个元素上执行XOR就可以实现更高效的解决方案 - 您甚至不需要排序数组!也就是说:

2^3^5^2^5^5^3 = 5
Run Code Online (Sandbox Code Playgroud)

我从Discrete Structures类回忆起,我认为Associate Property适用于XOR操作,这就是为什么这个解决方案有效:

a^a = 0
Run Code Online (Sandbox Code Playgroud)

和:

a^a^a = a
Run Code Online (Sandbox Code Playgroud)

虽然我记得Associative Property适用于XOR,但是我很难找到特定于XOR的这个属性的逻辑证明(因特网上的大多数逻辑证据似乎更侧重于AND和OR操作).有谁知道为什么关联属性适用于XOR操作?

我怀疑它涉及包含AND和/或OR的XOR身份.

c boolean-logic proof discrete-mathematics

11
推荐指数
1
解决办法
3544
查看次数

如何使用-std = gnu99编译Linux内核模块?

我最近学会了如何编写简单的字符驱动程序,在玩这些代码时,我注意到我的C99代码中出现了很多以下的GCC警告:

warning: ISO C90 forbids mixed declarations and code
Run Code Online (Sandbox Code Playgroud)

我假设这是因为主Linux内核Makefile设置为使用非C99标准进行编译.我在附近搜索我在stackoverflow上找到了这个答案:如何使用make和编译为C99?

所以我自然在我的Makefile中尝试了以下内容:

ccflags-y := -std=gnu99
Run Code Online (Sandbox Code Playgroud)

不幸的是,这并没有使GCC警告无声.我检查了详细的输出make并验证了GCC确实-std=gnu99在最后加上了; 所以我有点困惑.

如何使用该-std=gnu99选项正确编译Linux内核模块?

编辑:

我注意到GCC输出显示了这个选项:-Wdeclaration-after-statement.这是为什么即使有-std=gnu99选项我也会得到警告?

c linux gcc c99 linux-kernel

10
推荐指数
1
解决办法
5314
查看次数

为什么不调用`poll`在sysfs设备属性文件上正确阻塞?

我有一个简单的sysfs设备属性,显示在我的sysfs目录下,并在调用时read返回一个kernelspace变量的值.我想调用poll此属性以允许我的用户空间线程阻塞,直到属性显示的值发生更改.

我的问题是poll似乎没有阻止我的属性 - POLLPRI即使属性显示的值没有改变,它仍然会返回.实际上,我sysfs_notify在内核模块中根本没有调用,但用户空间调用poll仍然没有阻塞.

也许我应该检查比其他东西返回值POLLPRI-但根据文档的Linux内核,sysfs_poll应该返回POLLERR|POLLPRI:

/* ... When the content changes (assuming the
 * manager for the kobject supports notification), poll will
 * return POLLERR|POLLPRI ...
 */
Run Code Online (Sandbox Code Playgroud)

有什么我忘了做的事poll吗?


  1. device属性位于:/ sys/class/vilhelm/foo/blah.

  2. 我加载了一个名为foo的内核模块,它注册了一个设备,并创建了一个类和这个设备属性.

  3. 名为bar的用户空间应用程序生成一个调用poll设备属性的线程,检查POLLPRI.

    • 如果poll返回正数,POLLPRI则返回.
    • 使用fopenfscan从设备属性文件中读取值.
    • 如果值是 …

linux polling blocking linux-device-driver linux-kernel

10
推荐指数
1
解决办法
5545
查看次数

USER_HZ如何解决jiffy扩展问题?

据我所知,USER_HZ在Linux 2.6中添加了常量来解决HZ用户空间价值期望所引起的问题:在以前版本的Linux中,更改HZ值可能会导致用户空间应用程序中的值无意中缩放.

我对USER_HZ常量如何解决这个缩放问题感到困惑.例如,假设用户空间应用程序将jiffies转换为秒:

long MY_HZ = sysconf(_SC_CLK_TCK);

/* num_jiffies acquired from /proc but
 * simplified to 1000 here for clarity */
long num_jiffies = 1000;

long num_seconds = num_jiffies / MY_HZ;
Run Code Online (Sandbox Code Playgroud)

由于用户空间应用程序HZ通过sysconf调用确定值,这不会阻止扩展问题吗?

另一方面,如果用户空间应用程序确实将HZ硬编码到其源中,那么USER_HZ常量如何防止扩展问题 - 用户空间应用程序将使用其硬编码常量而不是系统USER_HZ,并且不能保证硬编码常数匹配USER_HZ

此外,用户空间(例如/proc)已经缩放到的所有时钟滴答值是否可用USER_HZ?用户空间程序如何知道jiffies中的值是缩放HZ还是USER_HZ

linux linux-kernel

10
推荐指数
2
解决办法
5911
查看次数

这个指针构建是否会破坏严格的别名规则?

这是Quake III Arena的快速反平方根实现:

float Q_rsqrt( float number )
{
        long i;
        float x2, y;
        const float threehalfs = 1.5F;

        x2 = number * 0.5F;
        y  = number;
        i  = * ( long * ) &y;                       // evil floating point bit level hacking
        i  = 0x5f3759df - ( i >> 1 );               // what?
        y  = * ( float * ) &i;
        y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
// …
Run Code Online (Sandbox Code Playgroud)

c pointers casting c99 strict-aliasing

9
推荐指数
2
解决办法
1062
查看次数

何时在扩展GCC内联汇编中使用earlyclobber约束?

我知道何时使用补鞋匠列表(例如列出在程序集中修改的寄存器,以便它不被选择用作输入寄存器等),但我无法绕过早期约束条件&.如果列出输出,那是否已经意味着输入不能使用所选寄存器(除了匹配数字约束)?

例如:

asm(
    "movl $1, %0;"
    "addl $3, %0;"
    "addl $4, %1;"
    "addl %1, %0;"
    : "=g"(num_out)
    : "g"(num_in)
    :
);
Run Code Online (Sandbox Code Playgroud)

&甚至需要为输出变量?编译器应该知道为输出选择的寄存器,因此知道不要将它用于输入.

c assembly gcc inline-assembly

9
推荐指数
2
解决办法
1913
查看次数

ftell在2GB以上的位置

在32位系统上,ftell如果以二进制模式打开的文件的当前位置指示符超过2GB点,会返回什么?在C99标准中,这是未定义的行为,因为ftell必须返回一个long int(最大值为2**31-1)?

c file-io stdio c99 ftell

9
推荐指数
2
解决办法
7636
查看次数

为什么fgets函数已被弃用?

来自GNU C编程教程:

fgets("文件中获取字符串")功能类似于获取功能.这个函数已被弃用 - 这意味着它已经过时,强烈建议你不要使用它 - 因为它很危险.这很危险,因为如果输入数据包含空字符,则无法分辨.fgets除非您知道数据不能包含null,否则请勿使用.不要使用它来读取用户编辑的文件,因为如果用户插入空字符,您应该正确处理它或打印清晰的错误消息.如果可以,请始终使用 getlinegetdelim代替fgets.

我觉得这个fgets功能在遇到a \0或者时会停止\n; 为什么当fgets应该正确处理输入时,这个手册页建议空字节是"危险的" ?此外,之间有什么区别getlinefgets,是fgets真正视为功能过时C99或将来的C标准?

c file-io gnu c99 buffer-overflow

8
推荐指数
2
解决办法
1万
查看次数

尝试插入访问导出符号的模块时出现"无效参数"错误

我正在尝试在两个模块之间共享一个全局变量,以便了解如何EXPORT_SYMBOL正确使用宏,但是Invalid paramaters当我尝试插入第二个模块时,我不断收到错误.

在第一个模块中foo.c:

#include <linux/module.h>
#include <linux/kernel.h>

extern unsigned myvar;
unsigned myvar = 42;
EXPORT_SYMBOL(myvar);

static int __init foo_init(void){
        printk(KERN_INFO "HELLO FROM MODULE 1");

        return 0;
}

static void __exit foo_exit(void){
        printk(KERN_INFO "BYE FROM MODULE 1");
}

module_init(foo_init);
module_exit(foo_exit);

MODULE_LICENSE("GPL");
Run Code Online (Sandbox Code Playgroud)

在第二个模块中bar.c:

#include <linux/module.h>
#include <linux/kernel.h>

extern unsigned myvar;

static int __init bar_init(void){
        printk(KERN_INFO "HELLO FROM MODULE 2");

        printk(KERN_INFO "myvar: %u", myvar);

        return 0;
}

static void __exit bar_exit(void){
        printk(KERN_INFO "BYE FROM MODULE …
Run Code Online (Sandbox Code Playgroud)

linux linux-device-driver linux-kernel

8
推荐指数
1
解决办法
3万
查看次数

为什么多维数组中的空字符串文字会衰减为空指针?

我想定义一个多维C字符串数组,该数组由多个字符串文字初始化。在C语言中,我将执行以下操作:

#include <stdio.h>

const char *strArr[2][1] = { {"foo"}, {""}};

int main(void) {
    printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在以下位置编译gcc -std=c18 -pedantic test.c并执行结果:

#include <stdio.h>

const char *strArr[2][1] = { {"foo"}, {""}};

int main(void) {
    printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如我所料,空字符串文字strArr[1][0]会衰减为有效的指针。


但是,当我在C ++中尝试相同的代码时:

#include <cstdio>

const char *strArr[2][1] = { {"foo"}, {""}};

int main(void) {
    printf("%p\t%p\n", strArr[0][0], strArr[1][0]);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在以下位置编译g++ -std=c++17 -pedantic test.cpp并执行结果:

$ ./a.out 
0x55d95410f004  0x55d95410f008 …
Run Code Online (Sandbox Code Playgroud)

c++ pointers g++ c-strings language-lawyer

8
推荐指数
1
解决办法
165
查看次数