对于许多问题,答案似乎可以在"标准"中找到.但是,我们在哪里找到它?最好是在线.
谷歌搜索有时会觉得徒劳,尤其是对于C标准,因为他们在编程论坛的大量讨论中被淹没.
要开始这个,因为这些是我现在正在搜索的,那里有很好的在线资源:
我正在维护一个脚本,可以从各种来源获取其输入,并按行进行处理.根据所使用的实际来源,换行符可能是Unix风格,Windows风格甚至是某些聚合输入,混合(!).
从文件中读取时,它会是这样的:
@lines = <IN>;
process(\@lines);
...
sub process {
@lines = shift;
foreach my $line (@{$lines}) {
chomp $line;
#Handle line by line
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我需要做的是将chomp替换为删除Unix风格或Windows风格的换行符.我想出太多方法来解决这个问题,这是Perl常见的缺点之一:)
您对扼杀通用换行符的最佳方式有什么看法?什么是最有效的?
编辑:一个小的澄清 - 方法'进程'从某个地方获取行列表,而不是从文件中读取nessecarily.每行可能有
我遇到了一些理论问题.在一段代码中,我维护着一组宏
#define MAX_OF_2(a, b) (a) > (b) ? (a) : (b)
#define MAX_OF_3(a, b, c) MAX_OF_2(MAX_OF_2(a, b), c)
#define MAX_OF_4(a, b, c, d) MAX_OF_2(MAX_OF_3(a, b, c), d)
...etc up to MAX_OF_8
Run Code Online (Sandbox Code Playgroud)
我想做的是用这样的东西替换它们:
/* Base case #1, single input */
#define MAX_OF_N(x) (x)
/* Base case #2, two inputs */
#define MAX_OF_N(x, y) (x) > (y) ? (x) : (y)
/* Recursive definition, arbitrary number of inputs */
#define MAX_OF_N(x, ...) MAX_OF_N(x, MAX_OF_N(__VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)
...当然,这是无效的预处理器代码.
忽略这个特殊情况应该使用函数而不是预处理器宏来解决,是否可以定义一个可变的MAX_OF_N()宏?
为了清楚起见,最终结果应该是一个宏,它接受任意数量的参数并评估其中最大的参数.我有一种奇怪的感觉,这应该是可能的,但我没有看到如何.
我正在看一些由公司其他部门维护的Java代码,偶然是一些以前的C和C++开发人员.无处不在的一件事是使用静态整数常量,例如
class Engine {
private static int ENGINE_IDLE = 0;
private static int ENGINE_COLLECTING = 1;
...
}
Run Code Online (Sandbox Code Playgroud)
除了缺乏"最终"限定符之外,我对这种代码感到有点困扰.我希望看到的是,从学校主要用Java培训,会更像
class Engine {
private enum State { Idle, Collecting };
...
}
Run Code Online (Sandbox Code Playgroud)
然而,这些论点让我失望.为什么,如果有的话,后者比前者更好?
我正在研究的代码应该可以为托管和独立环境构建,为后一种情况提供某些stdlib函数的私有实现.
我可以在普通的工作站/构建服务器上使用GCC进行可靠的测试吗?使用GCC编译独立环境
"-ffreestanding"选项看起来很有前途,但它似乎"只"禁用内置函数并正确设置STDC_HOSTED宏,它仍然提供所有系统头.
选项"-nostdinc"限制性太强; 我仍然想使用独立实现所需的头文件(特别是stddef.h和limits.h).
我在这里错过了什么?
哦,我现在正在使用GCC 4.4.3,很快就会升级到4.5.0.
我注意到在我们的代码库中的几个地方,我们使用动态扩展数组,即一个与元素计数器和"max elements"值相结合的基本数组.
我想要做的是用通常的数据结构和实用程序函数替换它们,这是出于通常的面向对象的原因.数组元素可以是基本数据类型或结构,我需要快速随机访问元素,最好是类型安全的实现.
所以,基本上,我想使用的是STL向量,但代码库仅限于C89所以我必须提出其他的东西:-)
我给了它一些想法并掀起了这个初稿,只是为了展示我的目标:
/* Type-safe dynamic list in C89 */
#define list_declare(type) typedef struct _##type##_list_t { type * base_array; size_t elements; size_t max_size; } type##_list_t
#define list(type) type##_list_t
#define list_new(type, initial_size) { calloc(initial_size, sizeof(type)), 0, initial_size }
#define list_free(list) free(list.base_array)
#define list_set(list, place, element) if ( list.elements < list.max_size ) { list.base_array[place] = element; } else { /* Array index out of bounds */ }
#define list_add(list, element) if ( list.elements < list.max_size ) { list.base_array[list.elements++] = element; …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用更新的构建系统; 目前,我正试图找到一种根据目标平台设置编译器和标志的好方法.
我想做的是像
switch $(PLATFORM)_$(BUILD_TYPE)
case "Linux_x86_release"
CFLAGS = -O3
case "Linux_x86_debug"
CFLAGS = -O0 -g
case "ARM_release"
CC = armcc
AR = armlink
CFLAGS = -O2 -fx
...
Run Code Online (Sandbox Code Playgroud)
这是GNU Make不支持的.现在,我的第一个想法就是做
-include $(PLATFORM)_$(BUILD_TYPE)
Run Code Online (Sandbox Code Playgroud)
这是一个相当不错的解决方案,然而,它很难概述文件之间的差异,更不用说我期待编写和维护一个好的60-80文件,每个文件包含一组变量定义.
有没有人碰巧知道更好的方法来实现这一目标?即根据另一个变量设置一组标志和其他选项?
我花了几分钟手动重新排序结构中的字段,以减少填充效果[1],这感觉就像几分钟太多.我的直觉是说我的时间可能更好地花在编写Perl脚本上,或者为我做这种优化.
我的问题是这是否也是多余的; 是否已经有一些我不知道的工具,或者我应该能够启用[2]打包结构的一些编译器功能?
由于需要在几种不同的体系结构中进行一致优化,因此使用的任何工具都需要能够考虑不同的结构对齐和指针大小,这个问题更加复杂.
编辑:快速澄清 - 我想要做的是重新排序源代码中的字段,以避免填充,而不是"编译"结构,而不是填充编译.
编辑#2:另一个复杂因素:根据配置,某些数据类型的大小也可能会发生变化.显而易见的是针对不同体系结构的指针和指针差异,但也有浮点类型(16,32或64位,取决于'精确性'),校验和(8位或16位取决于"速度")和一些其他不明显的东西.
[1]所讨论的结构在嵌入式设备上被实例化了数千次,因此结构的每个4字节减少可能意味着该项目的go和no-go之间的差异.
[2]可用的编译器是GCC 3.*和4.*,Visual Studio,TCC,ARM ADS 1.2,RVCT 3.*以及其他一些更加模糊的编译器.
我刚开始使用 C# 和 .NET,但我想尝试好好发挥并重用系统组件。
在我维护的代码中,有几个我们运行外部工具和应用程序的实例,如下所示:
using (var Setup = Process.Start(SetupInfo) )
{
Setup.WaitForExit(SetupTimeout);
if (!Setup.HasExited )
throw new TimeoutException(
"Setup did not complete within the expected time");
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试为那些具有明确定义的退出代码的外部工具添加退出代码的验证,即“using”块内的类似内容:
switch ( Setup.ExitCode )
{
case 0:
break;
case 1:
throw new SetupFailedException("Setup execution failed");
case 2:
throw new SetupFileNotFound("Setup did not find required files");
default:
throw new ExternalErrorException("Setup failed for some other reason");
}
Run Code Online (Sandbox Code Playgroud)
...其中前两个将派生自通用的“ExternalErrorException”。但是,是否有一些现有的通用异常我可以重复使用,即表明外部进程未能按预期运行,而不是发明我自己的异常?
我正在为一项服务进行一些测试自动化,并找到了一种巧妙的方法,将一些常见的设置和验证汇总到一个"会话"课程中.
从概念上讲,测试用例可能如下所示:
using (var managerSession = new Session(managerRole))
{
// A manager puts some items in warehouse
}
using (var employeeSession = new Session(employeeRole))
{
// An employee moves items from warehouse to store
}
using (var customerSession = new Session(customerRole))
{
// A customer can buy items from the store
}
Run Code Online (Sandbox Code Playgroud)
在Session对象构造函数中,我建立了与我正在测试的服务的连接,每个角色等都有适当的身份验证,并且在会话Dispose()方法中,我有一个通用的验证块,例如,检查没有服务器端错误或在会话期间提出警告.
现在,当然,这有点滥用IDispose模式,如果使用块内的测试代码抛出异常并且验证块也抛出异常,则第二个异常将掩盖第一个异常.
从概念上讲,如果我们有这种情况:
using (var managerSession = new Session(managerRole))
{
Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job");
}
Run Code Online (Sandbox Code Playgroud)
...并且断言失败或对managerSession.DoJob()的调用抛出异常,然后我希望Session Dispose()方法跳过验证块,即
public void Dispose()
{
if (NoExceptionThrown())
{
Assert.IsFalse(this.serviceConnection.HasErrors(), …Run Code Online (Sandbox Code Playgroud) 这是一个 Makefile 框架,只是为了更容易描述问题:
all_tests : unit_tests other_tests_1 other_tests_2 ... other_tests_N
unit_tests : set1_summary.txt set2_summary.txt ... setN_summary.txt
%_summary.txt : %_details.txt
perl createSummary.pl --in $^ -out $@
%_details.txt : test_harness
./test_harness --test-set $*
Run Code Online (Sandbox Code Playgroud)
因此,我有一个测试运行程序,可以生成包含详细结果的文件,然后使用过滤机制来创建摘要文件。
现在,如果测试集中的任何项目失败,测试运行程序应用程序将返回错误代码,这将正确中止“all_tests”目标并且永远不会调用 other_test 目标。但是,我想无条件地运行详细信息 -> 摘要转换,因为即使对于失败的测试运行,这也是相关的。
我尝试了一些不同的变体,但我可以使用的唯一方法是将整个命令链包装到 Perl 脚本中,存储第一个命令的结果并将其用作整个脚本的返回值。
但这感觉不是一个非常简洁的解决方案,特别是因为“实际”命令集比这个框架显示的要复杂一些。你知道有什么纯粹基于 GNU Make 的方法来完成这个任务吗?
这段代码有一个有趣的bug:
some_struct struct_array1[10] = {0};
some_struct struct_array2[10] = {0}
int i;
for (i = 0;
i < sizeof(struct_array1) / sizeof(struct_array1[0]);
struct_array1[i].value = struct_array2[i++].value = 1)
;
Run Code Online (Sandbox Code Playgroud)
对于大多数编译器,上面的代码导致将相应数组中所有结构的"value"字段设置为1.但是,对于一个特定的编译器(让我们称之为xcc),struct_array1中的结构未正确初始化.对于所有结构,"value"字段设置为0,这让我感到惊讶.
以下代码段在所有编译器上按预期工作:
for (i = 0;
i < sizeof(struct_array1) / sizeof(struct_array1[0]);
i++)
{
struct_array1[i].value = struct_array2[i].value = 1;
}
Run Code Online (Sandbox Code Playgroud)
现在,我完全离开这里,还是有问题的编译器"xcc"只是显示错误?
我在第一个代码片段中找不到任何显示特定于实现的行为的内容; 根据我的理解,后缀增量应该优先于赋值,并且应该从右到左评估赋值.第一个代码片段应该没什么奇怪的,除了它有点不可读.
我有一段带有以下粗略签名的代码:
void evaluate(object * this)
{
static const int briefList[] = { CONSTANT_A, CONSTANT_Z };
static const int fullList[] = { CONSTANT_A, CONSTANT_B, ..., CONSTANT_Z};
const int const * pArray;
const int nElements;
int i;
if ( this->needDeepsEvaluation )
{
pArray = fullList;
nElements = sizeof(fullList) / sizeof(fullList[0]);
}
else
{
pArray = briefList;
nElements = sizeof(briefList) / sizeof(briefList[0]);
}
for ( i = nElements; i; i-- )
{
/* A thousand lines of optimized code */
}
this->needsDeepEvaluation = …Run Code Online (Sandbox Code Playgroud)