小编jwd*_*jwd的帖子

GCC的标准替代## __ VA_ARGS__技巧?

C99中的可变参数宏存在一个众所周知的 空args 问题.

例:

#define FOO(...)       printf(__VA_ARGS__)
#define BAR(fmt, ...)  printf(fmt, __VA_ARGS__)

FOO("this works fine");
BAR("this breaks!");
Run Code Online (Sandbox Code Playgroud)

BAR()根据C99标准,上述用途确实不正确,因为它将扩展到:

printf("this breaks!",);
Run Code Online (Sandbox Code Playgroud)

请注意尾随逗号 - 不可行.

一些编译器(例如:Visual Studio 2010)将悄然摆脱那个尾随的逗号.其他编译器(例如:GCC)支持放在##前面__VA_ARGS__,如下所示:

#define BAR(fmt, ...)  printf(fmt, ##__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

但有没有符合标准的方法来获得这种行为?也许使用多个宏?

现在,该##版本似乎得到了相当好的支持(至少在我的平台上),但我真的更喜欢使用符合标准的解决方案.

先发制人:我知道我可以写一个小功能.我正在尝试使用宏来做到这一点.

编辑:以下是我想要使用BAR()的一个例子(虽然简单):

#define BAR(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)

BAR("here is a log message");
BAR("here is a log message with a param: %d", 42);
Run Code Online (Sandbox Code Playgroud)

这会自动为我的BAR()日志记录语句添加换行符,假设fmt它始终是双引号C字符串.它不会将换行符打印为单独的printf(),如果日志记录是行缓冲的并且异步来自多个源,则这是有利的.

c c99 c-preprocessor variadic-macros

141
推荐指数
6
解决办法
7万
查看次数

const双指针的惯用C语言

我知道,在C你不能隐式转换,例如,char**const char**(CF C-有问必答,SO问题1,SO问题2).

另一方面,如果我看到一个声明如此的函数:

void foo(char** ppData);
Run Code Online (Sandbox Code Playgroud)

我必须假设该函数可能会更改传入的数据.因此,如果我正在编写一个不会更改数据的函数,我认为最好声明:

void foo(const char** ppData);
Run Code Online (Sandbox Code Playgroud)

甚至:

void foo(const char * const * ppData);
Run Code Online (Sandbox Code Playgroud)

但这使得该功能的用户处于尴尬的境地.他们可能有:

int main(int argc, char** argv)
{
    foo(argv); // Oh no, compiler error (or warning)
    ...
}
Run Code Online (Sandbox Code Playgroud)

为了干净地调用我的函数,他们需要插入一个演员.

我来自一个主要是C++的背景,由于C++更深入的const规则,这不是一个问题.

C中惯用的解决方案是什么?

  1. 声明foo为a char**,并且只记录它不会改变其输入的事实?这看起来有点严重,尤其是 因为它惩罚那些可能const char**想要传递它的用户(现在他们必须抛弃常量)

  2. 强制用户投射他们的输入,增加常量.

  3. 别的什么?

c idioms const idiomatic

24
推荐指数
2
解决办法
2893
查看次数

产生一个线程是否自己提供内存顺序保证?

我想大致这样做:

初始线程:

  • 将一些值写入全局变量(它们将永远不会被再次写入)
    • 这可能是中等大的数据(数组、字符串等)。不能简单地制造std::atomic<>
  • 产生其他线程

其他线程:

  • 读取全局状态
  • 做工作等

现在,我知道我可以将参数传递给std::thread,但我试图通过这个例子来理解 C++ 的内存保证。

此外,我非常有信心,在任何现实世界的实现中,创建线程都会导致内存障碍,确保线程可以“看到”父线程在此之前编写的所有内容。

但我的问题是:这是由标准保证的吗?

旁白:我想我可以添加一些虚拟的东西std::atomic<int>,并在启动其他线程之前写入,然后在其他线程上,在启动时读取一次。我相信所有的happens-before 机制都可以保证先前编写的全局状态是正确可见的。

但我的问题是,技术上是否需要这样的东西,或者线程创建是否足够?

c++ multithreading

23
推荐指数
1
解决办法
1264
查看次数

为什么这个闭包没有修改封闭范围内的变量?

这一点Python不起作用:

def make_incrementer(start):
    def closure():
        # I know I could write 'x = start' and use x - that's not my point though (:
        while True:
            yield start
            start += 1
    return closure

x = make_incrementer(100)
iter = x()
print iter.next()    # Exception: UnboundLocalError: local variable 'start' referenced before assignment
Run Code Online (Sandbox Code Playgroud)

我知道如何解决这个错误,但请耐心等待:

这段代码工作正常:

def test(start):
    def closure():
        return start
    return closure

x = test(999)
print x()    # prints 999
Run Code Online (Sandbox Code Playgroud)

为什么我可以读取start闭包内的变量而不是写入它?导致这种start变量处理的语言规则是什么?

更新:我发现这个SO帖子相关(答案不仅仅是问题):读/写Python闭包

python closures generator

19
推荐指数
2
解决办法
6830
查看次数

跨平台ALIGN(x)宏?

我想创建一个struct具有一定对齐的.

我想对GCC和VisualC++编译器使用相同的结构定义.

在VisualC++中,通常会这样做:

__declspec(align(32))
struct MyStruct
{
// ...
};
Run Code Online (Sandbox Code Playgroud)

在GCC中,通常会这样做:

struct MyStruct
{
// ...
} __attribute__ ((aligned (32)));
Run Code Online (Sandbox Code Playgroud)

我当然可以创建适当的宏来使其工作:

BEGIN_ALIGNED_STRUCT(32)
struct
{
// ...
}
END_ALIGNED_STRUCT(32)
;
Run Code Online (Sandbox Code Playgroud)

因此能够透明地处理这两种情况,但在这里我必须复制对齐常量(32),我想避免.

在GCC另一种方法是把__attribute__结构体标签后,作为中提到的文档,就像这样:

struct __attribute__ ((aligned (32))) MyStruct
{
// ...
};
Run Code Online (Sandbox Code Playgroud)

因此我可以使这种类型的语法工作:

ALIGNED_STRUCT(32) MyStruct
{
// ...
};
Run Code Online (Sandbox Code Playgroud)

有没有人有更好的版本?其他想法?我尝试了一些代码搜索,但没有找到任何有希望的东西.


更新:基于@John的评论,这是另一个可以工作的版本(我没有编译它,但文档表明这是一个好主意)

struct MyStruct_Unaligned
{
// ...
};

TYPEDEF_ALIGNED(32, MyStruct_Unaligned, MyStruct);

// Would expand to one of:
// 
// typedef __declspec(align(32)) MyStruct_Unaligned MyStruct;
// …
Run Code Online (Sandbox Code Playgroud)

g++ memory-alignment visual-c++

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

与setw()有什么关系?

我最近被这样的事实所困扰:ios_base::width和/或setw操纵器必须在写入流的每个项目时重置.

也就是说,你必须这样做:

while(whatever)
{
    mystream << std::setw(2) << myval;
}
Run Code Online (Sandbox Code Playgroud)

而不是这个:

mystream.width(2);
while(whatever)
{
    mystream << myval;
}
Run Code Online (Sandbox Code Playgroud)

好的.

但有谁知道为什么做出这个设计决定?是否有一些我缺失的理由,或者这只是标准的一个黑暗角落?

其他流格式修饰符(如链接的SO问题中所述)是"粘性",而setw不是.

c++ setw c++-standard-library

16
推荐指数
2
解决办法
4357
查看次数

写入"内存文件"的Perl会播放模式匹配技巧

当我运行此代码时,我打印出"否":

my $memory_file;
my $fh;
open ($fh, '>', \$memory_file);
print $fh "abc";
if( $memory_file =~ m/^.*$/ )
{ print "yes\n" }
else
{ print "no\n" }
Run Code Online (Sandbox Code Playgroud)

如果我打印出来$memory_file,内容确实如此"abc".

如果我将模式更改为.*(no ^$)它按预期工作.

如果我$memory_file = "abc"在比赛前放线,我会打印出"是"(按照最初的预期).

这到底是怎么回事?

(这是perl 5.14.1)

更新:关于PerlMonks的更多讨论.它看起来像一个bug,我会记录它.

更新2:优秀的Perl开发人员修复了这个错误:https://rt.perl.org/rt3//Public/Bug/Display.html?id = 108398

regex perl

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

Bash括号粘贴 - 是否支持?

尽管做了一些努力,我还是无法获得Bash工作的"括号粘贴"功能.

我的终端是xterm支持它的.我的版本bash就是4.3.33(1)-release,我认为支持它的基础上的日期此线程.

我尝试在会话中启用它:

bind 'set enable-bracketed-paste on'
Run Code Online (Sandbox Code Playgroud)

但这似乎不起作用.

我尝试添加到我的.inputrc:

set enable-bracketed-paste on
Run Code Online (Sandbox Code Playgroud)

但也没有运气.

这个非常好的功能似乎记录很差,所以我很难找到信息......

这个好的概述页面说"......如果有人知道比bash用户更好的解决方案,而不是'切换到zsh',我想把它包含在这里." 但是在Bash进行更改之前,该页面已过时(请参阅上面提到的主题).

有没有人和Bash一起运气,在这里?我错过了什么魔法?

编辑:

我在这个链接上看到,在readline之前,括号内的粘贴可能无法使用7.0.我现在有6.3.也许这解释了吗?我不确定原始Bash线程的方块是如何的,它有一个readline补丁...

bash readline

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

透过Linq

我正在使用LINQ-to-Entities,并希望执行一个支点.

例如,我有这个表:

| data1 | data2 |
+-------+-------+
|   1   |   A   |
|   1   |   B   |
|   2   |   P   |
|   2   |   Q   |
|   2   |   R   |
+---------------+
Run Code Online (Sandbox Code Playgroud)

我想将其转换为以下结果:

| data1 | first | second | third |
+-------+-------+--------+-------+
|   1   |   A   |   B    | NULL  |
|   2   |   P   |   Q    |   R   |
+--------------------------------+
Run Code Online (Sandbox Code Playgroud)

我想在LINQ中执行此操作,而无需进行客户端处理.

我看过这些SO帖子,但是他们并没有完全解决上述情况(据我所知).



注意 我曾尝试以下,但它抱怨说,我不能在一个无序的集合使用跳过(),我没有看到一个办法让该集团的崩溃"数据2"信息进行排序.

from item in MyTable
group item by item.data1 into g …
Run Code Online (Sandbox Code Playgroud)

linq linq-to-entities pivot pivot-table sql-server-2008

7
推荐指数
1
解决办法
1196
查看次数

如何正确使用"PBEWithHmacSHA512AndAES_256"算法?

我正在做一些Java加密,并且无法找到正确使用PBEWithHmacSHA512AndAES_256算法的方法.

加密似乎工作正常,但我无法正确初始化解密密码.

以下是一个演示该问题的简短程序.特别是,请参阅"问题"评论.

注意:我已经看到了这个非常有用的答案,我可以使用该方案让事情发挥作用,但我很想知道我在这里做错了什么.

import java.nio.charset.StandardCharsets;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

public final class CryptQuestion {

    private static final String ALGORITHM = "PBEWithHmacSHA512AndAES_256";
    private static final int ITERATIONS = 1000; // Aside: not sure what is a good number, here.

    public static void main(final String[] args) throws Exception {
        final String message = "This is the secret message... BOO!";
        System.out.println("Original : " + message);
        final byte[] messageBytes = message.getBytes(StandardCharsets.US_ASCII);

        final String …
Run Code Online (Sandbox Code Playgroud)

java encryption aes password-encryption

7
推荐指数
1
解决办法
3959
查看次数