例:
#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你不能隐式转换,例如,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中惯用的解决方案是什么?
声明foo为a char**,并且只记录它不会改变其输入的事实?这看起来有点严重,尤其是 因为它惩罚那些可能const char**想要传递它的用户(现在他们必须抛弃常量)
强制用户投射他们的输入,增加常量.
别的什么?
我想大致这样做:
初始线程:
std::atomic<>。其他线程:
现在,我知道我可以将参数传递给std::thread,但我试图通过这个例子来理解 C++ 的内存保证。
此外,我非常有信心,在任何现实世界的实现中,创建线程都会导致内存障碍,确保线程可以“看到”父线程在此之前编写的所有内容。
但我的问题是:这是由标准保证的吗?
旁白:我想我可以添加一些虚拟的东西std::atomic<int>,并在启动其他线程之前写入,然后在其他线程上,在启动时读取一次。我相信所有的happens-before 机制都可以保证先前编写的全局状态是正确可见的。
但我的问题是,技术上是否需要这样的东西,或者线程创建是否足够?
这一点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闭包
我想创建一个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) 我最近被这样的事实所困扰: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不是.
当我运行此代码时,我打印出"否":
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
尽管做了一些努力,我还是无法获得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补丁...
我正在使用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) 我正在做一些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)