小编Sha*_*baz的帖子

在C中实现Goertzel算法

我正在DSP处理器上实现BFSK跳频通信系统.一些论坛成员建议使用Goertzel算法来解调特定频率的跳频.我已经尝试在C中实现goertzel算法.代码如下:

float goertzel(int numSamples,int TARGET_FREQUENCY,int SAMPLING_RATE, float* data)
{
    int     k,i;
    float   floatnumSamples;
    float   omega,sine,cosine,coeff,q0,q1,q2,result,real,imag;

    floatnumSamples = (float) numSamples;
    k = (int) (0.5 + ((floatnumSamples * TARGET_FREQUENCY) / SAMPLING_RATE));
    omega = (2.0 * M_PI * k) / floatnumSamples;
    sine = sin(omega);
    cosine = cos(omega);
    coeff = 2.0 * cosine;
    q0=0;
    q1=0;
    q2=0;

    for(i=0; i<numSamples; i++)
    {
        q0 = coeff * q1 - q2 + data[i];
        q2 = q1;
        q1 = q0;
    }
    real = (q1 - q2 * cosine);
    imag …
Run Code Online (Sandbox Code Playgroud)

c embedded signal-processing goertzel-algorithm

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

从多线程应用程序生成进程

我有一种情况,我需要从一个非常大的多线程应用程序中生成一个帮助程序进程,我没有完全控制.

现在我正在使用fork()/ exec().这在很多时候都有效,但在某些情况下,孩子在exec()发生之前会很奇怪地崩溃.我怀疑这是因为fork()多线程应用程序通常被认为是一个非常糟糕的想法.

我真的非常喜欢以原子方式启动进程的方法,不需要fork()父进程:关闭所有文件描述符,环境按照我想要的方式设置,CWD设置等等.这应该避免fork()我的多线程父应用程序的所有恐怖,处理文件描述符继承等posix_spawn()应该是理想的.不幸的是,在Linux上,posix_spawn()使用fork()和实现exec()...

vfork()被定义为暂停父进程,直到子进程调用exec().这似乎更像我想要的,但我的理解是,vfork()这些日子通常被认为是历史遗迹,相当于fork()---这仍然是这样吗?

处理这个问题的最不好的方法是什么?

注意:

  • 我不能在任何线程启动之前生成我的进程(因为我不能在那时运行代码)
  • 由于外部要求,我无法重新设计我的应用程序而不需要辅助进程
  • 在产生帮助程序进程之前,我无法暂停所有线程,因为它们不属于我

这是在Linux上.涉及Java,但我的所有代码都在C中.

c unix linux fork process

12
推荐指数
2
解决办法
2817
查看次数

重新定义标准名称是不确定的行为?

很容易理解这样的代码是如何工作的:

#include <string.h>

#define strcmp my_strcmp

int my_strcmp(const char *, const char *)

...
strcmp(str1, str2);
...
Run Code Online (Sandbox Code Playgroud)

但这个问题是这在技术上是否正确.

从C11:

7.1.3.1(关于保留名称):

...

  • 如果包含任何相关标头,则保留以下任何子条款中的每个宏名称(包括未来的库方向)以供指定使用; 除非另有明确说明(见7.1.4).
  • 在以下任何子条款(包括未来的库方向)和errno中具有外部链接的所有标识符始终保留用作具有外部链接的标识符.184)
  • 在以下任何子条款中列出的具有文件范围的每个标识符(包括未来的库方向)保留用作宏名称,并且如果包括任何相关联的标题,则用作具有相同名称空间的文件范围的标识符.

184具有外部链接的保留标识符列表包括math_errhandling,setjmp,va_copy和va_end.

所以这意味着这strcmp是一个保留字,因为string.h包括在内.

7.1.3.2:

...如果程序在保留它的上下文中声明或定义标识符(7.1.4允许的除外),或者将保留标识符定义为宏名称,则行为未定义.

现在这似乎说重新定义strcmp是未定义的行为,除了它在7.1.4中以某种方式允许.

7.1.4可能相关的内容是:

7.1.4.1:

...标头中声明的任何函数可以另外实现为标头中定义的类函数宏,因此如果在包含标头时显式声明了库函数,则可以使用下面显示的技术之一来确保声明不受这种宏的影响.通过将函数的名称括在括号中,可以在本地抑制函数的任何宏定义,因为该名称后面没有左括号,后面表示宏函数名称的扩展.出于相同的语法原因,即使它也被定义为宏,也允许获取库函数的地址.185)使用#undef删除任何宏定义也将确保引用实际函数....

185这意味着实现应为每个库函数提供实际函数,即使它还为该函数提供宏.

7.1.4.2:

如果可以在不引用标头中定义的任何类型的情况下声明库函数,则允许声明该函数并使用它而不包括其关联的标头.

其余条款无关紧要.我没有看到7.1.3.2指的是"7.1.4允许的",除了与函数相同的头中的库函数的定义,即标准头,作为宏.

总之,上面的代码是技术上未定义的行为吗?如果string.h不包括在内怎么样?

c language-lawyer

12
推荐指数
2
解决办法
766
查看次数

无论如何,VLA有什么意义?

我理解变量长度数组是什么以及它们是如何实现的.这个问题是关于他们存在的原因.

我们知道VLA只允许在功能块(或原型)中使用,并且它们基本上不能在堆栈上的任何地方(假设正常实现):C11,6.7.6.2-2:

如果标识符被声明为具有可变修改类型,则它应该是普通标识符(如6.2.3中所定义),没有链接,并且具有块范围或函数原型范围.如果标识符被声明为具有静态或线程存储持续时间的对象,则它不应具有可变长度数组类型.

我们举一个小例子:

void f(int n)
{
    int array[n];
    /* etc */
}
Run Code Online (Sandbox Code Playgroud)

有两种情况需要注意:

  • n <= 0:f必须防范这一点,否则行为是不明确的:C11,6.7.6.2-5(强调我的):

    如果size是一个不是整数常量表达式的表达式:如果它出现在函数原型范围的声明中,则将其视为替换为*; 否则, 每次评估它时,其值应大于零.可变长度数组类型的每个实例的大小在其生命周期中不会改变.如果size表达式是运算sizeof符操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式.

  • n > stack_space_left / element_size:没有标准的方法可以找到剩余多少堆栈空间(因为只要涉及标准就没有堆栈这样的东西).所以这个测试是不可能的.只有明智的解决方案才是拥有预定义的最大可能大小n,例如N,确保不会发生堆栈溢出.

换句话说,程序员必须确保0 < n <= N一些N选择.但是,程序应该n == N仍然可以工作,所以人们也可以声明数组的大小N是常量而不是可变长度n.

我知道引入了VLA以替换alloca(在本回答中也提到过),但实际上它们是相同的(在堆栈上分配可变大小的内存).

所以问题是为什么allocaVLA存在并且因此VLA存在以及它们为什么不被弃用?在我看来,使用VLA的唯一安全方法是使用有限大小,在这种情况下,采用具有最大大小的正常阵列始终是可行的解决方案.

c variable-length-array

12
推荐指数
4
解决办法
8382
查看次数

什么是create_proc_entry()的替代方案

由于create_proc_entry功能已被弃用,它的替代品是什么?我试图创建一个简单的proc条目,create_proc_entry但得到了这个错误:

错误:函数'create_proc_entry'的隐式声明

create_proc_entry在proc_fs.h中抓了一下但是没找到它.有什么东西我缺少或有替代方法吗?

linux-kernel procfs

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

如何解析通过/ proc文件传递给内核模块的大量数据?

编辑:我发现seq_file很容易从内核向用户空间写入大量数据.我正在寻找的是相反的; 一个API,便于从用户空间读取大量数据(多个页面).

编辑2:我正在实现一个<stdio.h>作为内核模块的端口,它能够打开/proc(以及后来的其他虚拟文件系统),类似于FILEs并处理类似的输入和输出<stdio.h>.你可以在这里找到这个项目.


我发现了很多关于内核如何将大量数据写入/ proc(用于用户空间程序)的问题,但没有其他方面.让我详细说明:

这个问题基本上是关于输入被标记化的算法(例如ints或混合int和字符串等),假设数据可能在多个缓冲区之间被打破.

例如,假设以下数据被发送到内核模块:

12345678 81234567 78123456 67812345 5678 1234 45678123 3456 7812 23456781
Run Code Online (Sandbox Code Playgroud)

并且为了这个例子,假设Linux提供/ proc处理程序的页面大小是20字节(相对于真正的4KB).

从/ proc(在内核模块中)读取数据的函数然后查看数据:

call 1:
"12345678 81234567 78"
call 2:
"123456 67812345 5678"
call 3:
" 1234 45678123 3456 "
call 4:
"7812 23456781"
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,当78在第一次调用中读取时,它应该在下一帧之前处理,以便它决定78帧之间是整数还是一帧.

现在我发现seq_files显然只是在内核想要数据写入用户而不是读取时(或者可能是HOWTO写得非常糟糕).

我做了什么

到目前为止,我已经提出了以下解决方案(我是从记忆中写的,所以我可能会错过几次错误检查,但请耐心等待):

在初始化阶段(比如说init_module …

c linux buffer kernel procfs

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

成员函数指针和继承

我需要解决这个问题.有一个基类和两个继承的类.基类包含需要函数指针作为参数的方法.但是这些函数是在继承的类中定义的.

class CBase;

typedef bool (CBase::*FPredicate)();

class CBase
{
public:
    CBase() {}
    ~CBase() {}
protected:
    //this method waits until 'predicate' is true or until 'timeout' ms. passed
    //and returns true if 'predicate' is true eventually
    bool WaitEvent(FPredicate predicate, int timeout)
    {
        bool result = false;
        int time1 = GetTickCount();
        int time2;

        bool isEnd = false;
        while(!isEnd)
        {
            result = isEnd = (this->*predicate)();              

            time2 = GetTickCount();
            if(time2 - time1 > timeout && !isEnd)
                isEnd = true;
        }
        return result;
    }
}; …
Run Code Online (Sandbox Code Playgroud)

c++ inheritance member-function-pointers

9
推荐指数
1
解决办法
945
查看次数

实现不同但相似的结构/功能集而无需复制粘贴

我正在为C(这里)实现一组常见但又不那么简单(或容易出错)的数据结构,并且只是提出了让我思考的想法.

简而言之,问题是,实现两个使用类似算法但具有不同接口的结构的最佳方法是什么,而无需复制粘贴/重写算法?最好的,我的意思是最可维护和可调试.

我认为很明显为什么你不想要同一算法的两个副本.

动机

假设你有一组结构(称之为map),带有一组相关的函数(map_*()).由于地图需要将任何东西映射到任何东西,我们通常会使用a void *keyvoid *data.然而,认为地图上的intint.在这种情况下,您需要将所有密钥和数据存储在另一个阵列中并将其地址提供给map,这不太方便.

现在想象一下,如果有一个类似的结构(称之为mapc,C为"副本")期间初始化需要sizeof(your_key_type)sizeof(your_data_type)并给予void *keyvoid *data上插入,它将使用memcpy的密钥和数据复制在地图上,而不是仅仅维持指针.用法示例:

int i;
mapc m;
mapc_init(&m, sizeof(int), sizeof(int));
for (i = 0; i < n; ++i)
{
    int j = rand();  /* whatever */
    mapc_insert(&m, &i, &j);
}
Run Code Online (Sandbox Code Playgroud)

这是非常好的,因为我不需要保留另一个is和js 数组.

我的想法

在上面的例子,mapmapc有非常密切的关系.如果你想想看,map和 …

c interface abstract-data-type data-structures

9
推荐指数
1
解决办法
357
查看次数

fsync,sync:它真的做到了应有的意义吗?

我想更详细地说明Linux(2.6.31)中sync(8)和fsync函数的功能.它是否确保将文件写入相应的存储?

linux filesystems linux-device-driver embedded-linux

9
推荐指数
1
解决办法
6706
查看次数

"int"和"float"上的三元运算符的结果

简而言之,我有以下代码:

float x = cond ? 0 : x_option;
Run Code Online (Sandbox Code Playgroud)

where x_option是a template<float>,它有一个operator float()(没有其他自动转换操作符.注意转换后表达式的类型:

bool ? int : float;
Run Code Online (Sandbox Code Playgroud)

我希望这个表达式的结果是float:


C11:

如果第二个和第三个操作数都具有算术类型,那么通常的算术转换确定的结果类型是应用于这两个操作数的结果类型.

所以它遵循相同的规则float + int.


C++ 11:

第二和第三个操作数具有算术或枚举类型; 执行通常的算术转换以使它们成为公共类型,结果是该类型.

同样的规则.


但是,clang和cl.exe都会vcvttss2si在导致评估第3个参数的路径中生成一条指令,即它们决定结果bool ? int : float是a int,而不是float!

为了公平起见,C++ 11有一个我引述前,应申请,并要诚实一些规则,这些规则不是最容易理解的,虽然从我可以做的话,转换int应该是不可能的:

C++ 11:

否则,如果第二个和第三个操作数具有不同的类型并且具有(可能是cv限定的)类类型,或者两者都是相同值类别的glvalues和除cv-qualification之外的相同类型,则尝试转换每个那些操作数与另一种操作数的关系.确定类型T1的操作数表达式E1是否可以转换为匹配类型T2的操作数表达式E2的过程定义如下:

- 如果E2是左值:如果E1可以被隐式转换(第4节)到类型"左值引用T2",则E1可以被转换为匹配E2,受制于转换中引用必须直接绑定的约束(8.5. 3)到左值.

- 如果E2是x值:如果E1可以隐式转换为"rvalue reference to T2"类型,则E1可以转换为匹配E2,受限于引用必须直接绑定.

- 如果E2是一个右值,或者上面的转换都不能完成,并且至少有一个操作数具有(可能是cv-qualified)类类型:

  • 如果E1和E2具有类类型,并且底层类类型相同或者一个是另一个类的基类:如果T2的类与类的类型相同,则可以转换为E1,或者基类类, T1的类别和T2的cv资格是与cv资格相同的cv资格或更高的cv资格.如果应用转换,则通过从E1复制初始化T2类型的临时值并将该临时值用作转换后的操作数,将E1更改为类型T2的prvalue.

  • 否则(即,如果E1或E2具有非类型类型,或者如果它们都具有类类型但基础类不是相同或者是另一个类的基类):如果E1可以是E1,则可以将E1转换为匹配E2如果E2被转换为prvalue(或者它具有的类型,如果E2是prvalue),则隐式转换为表达式E2将具有的类型.

使用该过程,确定是否可以转换第二操作数以匹配第三操作数,以及是否可以转换第三操作数以匹配第二操作数.如果两者都可以转换,或者一个可以转换,但转换不明确,则程序格式不正确.

根据我在上面的理解,这属于第三种情况的第二种情况(最后一个项目符号点的最后一个要点),因此E1(类型int)应该转换为E2(float)的类型.该标准后来表示,如果转换可以双向完成,那么该程序就是格式错误.

这里的裁决是什么?我处于未定义的行为领域吗?或者是标准规定我所看到的转换?

c++ language-lawyer c++11

9
推荐指数
1
解决办法
572
查看次数