C语言 如何在C中生成GUID?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7399069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generate a GUID in C?
提问by chacham15
I want to generate guids to insert into a SQLite database (i.e. no support from the db itself). However, I would like to have control over certain properties:
我想生成 guids 以插入到 SQLite 数据库中(即不支持 db 本身)。但是,我想控制某些属性:
- Orderedness for generating increasing guid values.
- Computer independence. The db is public and may/may not want guids to allow someone to trace data back to a specific machine.
- 'Enough' randomness. The guids are keys in the db which is going to be merged with a lot of other dbs and can get quite large, meaning that faking a guid like many algorithms do is no good.
- I can deal with using system specific APIs but please link both Windows and Linux functions, and something like SQLite is preferred, where I can just use code someone else wrote.
- I would also prefer code which is OK to use in a commercial application.
- 生成递增 guid 值的有序性。
- 计算机独立。db 是公共的,可能/可能不希望 guid 允许某人将数据追溯到特定机器。
- “足够”的随机性。guid 是 db 中的键,它将与许多其他 db 合并,并且可能会变得非常大,这意味着像许多算法那样伪造 guid 是不好的。
- 我可以处理使用系统特定的 API,但请同时链接 Windows 和 Linux 函数,并且首选 SQLite 之类的东西,我可以只使用其他人编写的代码。
- 我也更喜欢可以在商业应用程序中使用的代码。
采纳答案by paercebal
You can either use or look at the code of Boost.Uuid :
您可以使用或查看 Boost.Uuid 的代码:
http://www.boost.org/doc/libs/1_47_0/libs/uuid/index.html
http://www.boost.org/doc/libs/1_47_0/libs/uuid/index.html
It is a C++ library, but still, you can find inside how the code author retrieved the Uuid on multiple systems. Last time I checked (january 2010), I found at least the following implementations for Windows and Linux/Solaris (this info could be outdated):
它是一个 C++ 库,但仍然可以在代码作者如何在多个系统上检索 Uuid 中找到。上次检查时(2010 年 1 月),我发现至少有以下适用于 Windows 和 Linux/Solaris 的实现(此信息可能已过时):
UUID/GUID on Linux/Solaris
Linux/Solaris 上的 UUID/GUID
Open a file to /dev/urandomand read enough bytes (16) to make up a GUID/UUID.
打开文件/dev/urandom并读取足够的字节 (16) 以组成 GUID/UUID。
UUID/GUID on Windows
Windows 上的 UUID/GUID
Use the following WinAPI functions
使用以下 WinAPI 函数
- CryptAcquireContextto acquire a random context
- CryptReleaseContextto release the acquired random context
- CryptGenRandomto generate enough bytes to make up a GUID/UUID
- CryptAcquireContext获取随机上下文
- CryptReleaseContext释放获取的随机上下文
- CryptGenRandom生成足够的字节来组成 GUID/UUID
Other implementations
其他实现
The Wikipedia page on GUID/UUID has a list of alternative implementations you could use/study:
GUID/UUID 上的维基百科页面列出了您可以使用/研究的替代实现:
https://en.wikipedia.org/wiki/UUID#Implementations
https://en.wikipedia.org/wiki/UUID#Implementations
About your conditions
关于你的条件
There is a GUID/UUID type which is always random (the version 4), meaning that to be compatible with other GUID/UUID semantics, you should respect that.
有一个始终随机的 GUID/UUID 类型(版本 4),这意味着要与其他 GUID/UUID 语义兼容,您应该尊重它。
Now, you want the GUID/UUID to be ordered in time. The only way to do that without weakening the GUID/UUID randomness would be to prefix the 16-byte GUID/UUID with an unsigned integer (which would make your identifier data 20-bytes, or more, depending on your integer). Just generate a GUID/UUID, and increase the integer.
现在,您希望及时订购 GUID/UUID。在不削弱 GUID/UUID 随机性的情况下做到这一点的唯一方法是在 16 字节 GUID/UUID 前面加上一个无符号整数(这将使您的标识符数据成为 20 字节或更多,具体取决于您的整数)。只需生成一个 GUID/UUID,并增加整数。
回答by E Net Arch
One place to look for an answer to creating a GUID that contains many of the elements the author is looking for is in PHP .. http://us3.php.net/uniqid.. In their examples, they discuss how to add server names, database names, and other elements to a GUID.
寻找创建包含作者正在寻找的许多元素的 GUID 的答案的一个地方是 PHP .. http://us3.php.net/uniqid.. 在他们的示例中,他们讨论了如何添加服务器名称、数据库名称和其他元素到 GUID。
However, to address the need for a C based GUID function, here is code based on a JavaScript function .. Create GUID / UUID in JavaScript?.. this example uses RegEx to create the GUID.
但是,为了满足对基于 C 的 GUID 函数的需求,这里是基于 JavaScript 函数的代码。在 JavaScript 中创建 GUID/UUID?.. 本示例使用 RegEx 创建 GUID。
Below is code that will create a GUID based on the JavaSCript example. I'm sure there are more elegant solutions out there. This is something cobbled together to help give a clean example for others to follow.
下面是基于 JavaSCRipt 示例创建 GUID 的代码。我相信那里有更优雅的解决方案。这是拼凑起来的东西,以帮助为其他人提供一个干净的榜样。
srand (clock());
char GUID[40];
int t = 0;
char *szTemp = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
char *szHex = "0123456789ABCDEF-";
int nLen = strlen (szTemp);
for (t=0; t<nLen+1; t++)
{
int r = rand () % 16;
char c = ' ';
switch (szTemp[t])
{
case 'x' : { c = szHex [r]; } break;
case 'y' : { c = szHex [r & 0x03 | 0x08]; } break;
case '-' : { c = '-'; } break;
case '4' : { c = '4'; } break;
}
GUID[t] = ( t < nLen ) ? c : 0x00;
}
printf ("%s\r\n", GUID);
Note: strings end with a 0x00 character.
注意:字符串以 0x00 字符结尾。
回答by Skizz
First off, GUIDs aren't random, they are very well defined mathmatically.
首先,GUID 不是随机的,它们在数学上有很好的定义。
As for your problem, put the GUID creation into the database itself as a stored procedure, that way the system is platform independent. Then, make the GUID an auto-incrementing integer prefixed with a database ID. The prefix allows databases to be merged easily. The database ID needs to be unique for each database. If you control each database then it is straightforward to ensure these are unique. Otherwise you may need a lookup system which maps the database IP address (or some other unique identifier) to a unique database ID.
至于您的问题,请将 GUID 创建作为存储过程放入数据库本身,这样系统就与平台无关。然后,使 GUID 成为带有数据库 ID 前缀的自动递增整数。前缀允许轻松合并数据库。每个数据库的数据库 ID 需要是唯一的。如果您控制每个数据库,则很容易确保它们是唯一的。否则,您可能需要一个将数据库 IP 地址(或某些其他唯一标识符)映射到唯一数据库 ID 的查找系统。
If you don't have stored procedures then create a table with "NextIndex" and "DatabaseID" fields and update them when a new record is added:
如果您没有存储过程,则创建一个包含“NextIndex”和“DatabaseID”字段的表,并在添加新记录时更新它们:
read NextIndex and DatabaseID
increment NextIndex
ID = NextIndex + DatabaseID
add new record, setting "GUID" to the ID value

