在未能获得类似以下内容的编译之后:
public class Gen<T> where T : System.Array
{
}
Run Code Online (Sandbox Code Playgroud)
有错误
约束不能是特殊的类`System.Array'
我开始疑惑,究竟什么是 "特殊班级"?
当人们System.Enum在泛型约束中指定时,人们似乎经常会遇到同样的错误.我得到了相同的结果System.Object,System.Delegate,System.MulticastDelegate和System.ValueType也.
还有更多吗?我在C#中找不到关于"特殊类"的任何信息.
此外,什么是如此特殊的,我们不能把它们作为一个泛型类型约束类?
在名称方面我的想象力很弱,所以我经常发现自己在代码中重用了标识符.这导致我遇到这个特定的问题.
这是一些示例代码:
public delegate void TestDelegate(int test);
public class Test
{
private int test;
private void method(int aaa)
{
TestDelegate del = test => aaa++;
test++;
}
public static void Main()
{
}
}
Run Code Online (Sandbox Code Playgroud)
以下是编译错误(由ideone输出):
prog.cs(11,3): error CS0135: `test' conflicts with a declaration in a child block
prog.cs(9,22): (Location of the symbol related to previous error)
Compilation failed: 1 error(s), 0 warnings
Run Code Online (Sandbox Code Playgroud)
第11 test++行包含第9行包含lambda.
顺便说一下,Visual Studio 2013给出了不同的错误:
'test' conflicts with the declaration 'Namespace.Test.test'
Run Code Online (Sandbox Code Playgroud)
该错误仅在第11行的增量处发生.
如果我注释掉第9行(lambda)或第11行(增量),代码会成功编译.
这个问题让我感到惊讶 - …
寻找有关内联函数的静态解析类型参数的信息,我偶然发现了FSharp.Core 中各种原始运算符的定义:
let inline (+) (x: ^T) (y: ^U) : ^V =
CheckedAdditionDynamic<(^T),(^U),(^V)> x y
when ^T : int32 and ^U : int32 = (# "add.ovf" x y : int32 #)
when ^T : float and ^U : float = (# "add" x y : float #)
// <snip>
when ^T : ^T = ((^T or ^U): (static member (+) : ^T * ^U -> ^V) (x,y))
Run Code Online (Sandbox Code Playgroud)
从上面的代码片段中可以看出,when关键字的使用格式为:when expr1 = expr2适用于各种内置类型.我猜这是某种编译器相当于"如果T = int使用opcode add.ovf,否则如果......,否则就这样做". …
出于何种目的,在此代码中使用循环
public final int getAndSet(int newValue) {
for (;;) {
int current = get();
if (compareAndSet(current, newValue))
return current;
}
}
Run Code Online (Sandbox Code Playgroud) 在C中,我相信以下程序是有效的:将指向已分配内存缓冲区的指针转换为如下数组:
#include <stdio.h>
#include <stdlib.h>
#define ARRSIZE 4
int *getPointer(int num){
return malloc(sizeof(int) * num);
}
int main(){
int *pointer = getPointer(ARRSIZE);
int (*arrPointer)[ARRSIZE] = (int(*)[ARRSIZE])pointer;
printf("%d\n", sizeof(*arrPointer) / sizeof((*arrPointer)[0]));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(这输出4).
但是,在C99中,使用VLA进行此操作是否安全?
int arrSize = 4;
int *pointer = getPointer(arrSize);
int (*arrPointer)[arrSize] = (int(*)[arrSize])pointer;
printf("%d\n", sizeof(*arrPointer) / sizeof((*arrPointer)[0]));
return 0;
Run Code Online (Sandbox Code Playgroud)
(也是输出4).
根据C99标准,这是否合法?
如果它是合法的,那将是很奇怪的,因为这意味着VLA有效地启用动态类型创建,例如,类型的类型type(*)[variable].
昨天,我向朋友们解释了C#的通用限制.在展示where T : CLASSNAME约束时,我掀起了这样的事情:
public class UnusableClass<T> where T : UnusableClass<T>
{
public static int method(T input){
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
并且看到它编译真的很惊讶.然而,经过一番思考之后,我认为从编译器的角度来看它是完全合法的 - UnusableClass<T>与其他任何可用于此约束的类一样多.
然而,这留下了几个问题:如何使用这个类?是否有可能
int method?如果是的话,怎么样?
如果其中任何一种都可能,那么它的类型T是什么?
我一直在研究在C11前C中实现结构"多态"的非传统方式.假设我们有2个结构:
struct s1 {
int var1;
char var2;
long var3;
};
struct s2 {
int var1;
char var2;
long var3;
char var4;
int var5;
};
Run Code Online (Sandbox Code Playgroud)
在大多数编译器中,我们可以安全地在指向两者的指针之间进行转换,然后在没有填充的情况下访问公共的第一个成员.但是,这不是标准化的行为.
现在,我在C标准中找到了以下C89行:
为了简化联合的使用,我们做了一个特殊的保证:如果一个联合包含几个共享一个共同初始序列的结构,并且如果联合对象当前包含这些结构中的一个,则允许检查任何共同的初始部分.他们 如果相应的成员具有一个或多个初始成员的序列的兼容类型,则两个结构共享共同的初始序列.
它还说明了以下内容:
指向联合对象的指针(适当地强制转换)指向其每个成员(或者如果成员是位字段,则指向它所在的单元),反之亦然.
现在,如果我创建这两个结构的联合:
union s2_polymorphic {
struct s1 base;
struct s2 derived;
};
Run Code Online (Sandbox Code Playgroud)
并以这种方式使用它:
union s2_polymorphic test_s2_polymorphic, *ptest_s2_polymorphic;
struct s2 *ptest_s2;
struct s1 *ptest_s1;
ptest_s2_polymorphic = &test_s2_polymorphic;
ptest_s2 = (struct s2*)ptest_s2_polymorphic;
ptest_s2->var1 = 1;
ptest_s2->var2 = '2';
ptest_s1 = (struct s1*)ptest_s2;
printf("ptest_s1->var1 = %d\n", ptest_s1->var1);
printf("ptest_s1->var2 = %c\n", ptest_s1->var2);
Run Code Online (Sandbox Code Playgroud)
编译并运行良好,并在gcc(GCC)4.8.3 …
我对C99的可变修改型系统感兴趣.这个问题的灵感来自于这个问题.
检查这个问题的代码,我发现了一些有趣的东西.考虑以下代码:
int myFunc(int, int, int, int[][100]);
int myFunc(int a, int b, int c, int d[][200]) {
/* Some code here... */
}
Run Code Online (Sandbox Code Playgroud)
这显然不会(也不会)编译.但是,这段代码:
int myFunc(int, int, int, int[][100]);
int myFunc(int a, int b, int c, int d[][c]) {
/* Some code here... */
}
Run Code Online (Sandbox Code Playgroud)
编译甚至没有警告(在gcc上).
这似乎意味着可变修改的阵列类型与任何非可变修改的阵列类型兼容!
但那还不是全部.您期望一种可变修改类型至少可以使用哪个变量来设置其大小.但它似乎没有这样做!
int myFunc(int, int b, int, int[][b]);
int myFunc(int a, int b, int c, int d[][c]) {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
也编译没有任何错误.
所以,我的问题是:这是正确的标准化行为吗?
此外,如果一个可变修改的数组类型真的与任何具有相同维度的数组兼容,那么这不会意味着令人讨厌的安全问题吗?例如,请考虑以下代码:
int myFunc(int a, int b, int c, int …Run Code Online (Sandbox Code Playgroud) 如果有人回答我的问题,请不要告诉我使用C++.
所以,我在C中创建了一个使用面向对象方法的小型库.我选择在C中使用两种主要的继承方法中较不常见的方法:将基类型的成员复制到派生类型的开头.像这样的东西:
struct base {
int a;
int b;
char c;
};
struct derived {
int a;
int b;
char c;
unsigned int d;
void (*virtual_method)(int, char);
};
Run Code Online (Sandbox Code Playgroud)
这种方法不如另一种方法(基类型的实例作为派生类型的第一个成员)受欢迎,因为
但是,与其他方法相比,它也有其优点:
我一直在寻找使我的库编译和使用强制执行严格别名(如gcc)的编译器正确工作的可能性,而无需用户手动关闭它.以下是我研究过的可能性:
工会.遗憾的是,由于以下几个原因,这些是禁忌:
使用memcpy而不是直接解除引用(如此处).这看起来是个不错的解决方案.但是,函数调用会产生开销,是的,再一次,冗长.据我所知,memcpy也可以通过将指向结构的指针强制转换为指针char然后解除引用来手动完成,如下所示:(member_type)(*((char*)(&struct_pointer->member))) = new_value;Gah,再次详述.好吧,这可以用宏包裹.但是,如果我们将指针转换为指向不兼容类型的指针,然后将其转换为char*并取消引用它,那么它仍然可以工作吗?像这样:(member_type)(*((char*)(&((struct incompatible_type*)struct_pointer)->member))) = new_value;
声明我们将要转换为的所有类型实例 …
我的印象是C#中的lambda表达式上下文包含对其中使用的父函数作用域的变量的引用.考虑:
public class Test
{
private static System.Action<int> del;
public static void test(){
int i = 100500;
del = a => System.Console.WriteLine("param = {0}, i = {1}", a, i);
del(1);
i = 10;
del(1);
}
public static void Main()
{
test();
}
}
Run Code Online (Sandbox Code Playgroud)
输出
param = 1, i = 100500
param = 1, i = 10
Run Code Online (Sandbox Code Playgroud)
但是,如果这是真的,则以下内容将是非法的,因为lambda上下文将引用超出范围的局部变量:
public class Test
{
private static System.Action<int> del;
public static void test(){
int i = 100500;
del = a => System.Console.WriteLine("param = {0}, …Run Code Online (Sandbox Code Playgroud)