如何在C中生成GUID?

时间:2011-09-13 08:45:47

标签: c guid uuid

我想生成guid以插入SQLite数据库(即不支持db本身)。但是,我想控制某些属性:

  1. 用于生成增加的guid值的有序性。
  2. 计算机独立性。数据库是公共的,可能/可能不希望guids允许某人将数据跟踪回特定的计算机。
  3. '足够'随机性。 guid是db中的键,它将与许多其他dbs合并,并且可以变得非常大,这意味着伪造像许多算法一样的guid是不行的。
  4. 我可以处理使用系统特定的API,但是请链接Windows和Linux功能,而像SQLite这样的东西是首选的,我可以使用别人写的代码。
  5. 我也更喜欢在商业应用程序中使用的代码。

4 个答案:

答案 0 :(得分:5)

寻找创建包含作者正在寻找的许多元素的GUID的答案的地方是PHP .. http://us3.php.net/uniqid ..在他们的示例中,他们讨论了如何添加服务器名称,数据库GUID的名称和其他元素。

但是,为了满足基于C的GUID函数的需要,这里是基于JavaScript函数的代码。Create GUID / UUID in JavaScript? ..此示例使用RegEx创建GUID。

下面是将根据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);

注意:字符串以0x00字符结尾。

答案 1 :(得分:4)

首先,GUID不是随机的,它们的数学定义非常好。

至于您的问题,将GUID创建作为存储过程放入数据库本身,这样系统与平台无关。然后,使GUID成为一个以数据库ID为前缀的自动递增整数。前缀允许轻松合并数据库。每个数据库的数据库ID都必须是唯一的。如果您控制每个数据库,则可以直接确保这些数据库是唯一的。否则,您可能需要一个查找系统,将数据库IP地址(或其他一些唯一标识符)映射到唯一的数据库ID。

如果您没有存储过程,则创建一个包含“NextIndex”和“DatabaseID”字段的表,并在添加新记录时更新它们:

read NextIndex and DatabaseID
increment NextIndex
ID = NextIndex + DatabaseID
add new record, setting "GUID" to the ID value

答案 2 :(得分:3)

您可以使用或查看Boost.Uuid的代码:

http://www.boost.org/doc/libs/1_47_0/libs/uuid/index.html

它是一个C ++库,但你仍然可以在里面找到代码作者如何在多个系统上检索Uuid。上次我检查(2010年1月)时,我发现至少Windows和Linux / Solaris的以下实现(此信息可能已过时):

Linux / Solaris上的UUID / GUID

打开文件到/dev/urandom并读取足够的字节(16)以构成GUID / UUID。

Windows上的UUID / GUID

使用以下WinAPI函数

其他实施

GUID / UUID上的Wikipedia页面列出了您可以使用/学习的替代实现:

https://en.wikipedia.org/wiki/UUID#Implementations

关于您的条件

GUID / UUID类型始终是随机的(version 4),这意味着要与其他GUID / UUID语义兼容,您应该尊重它。

现在,您希望及时订购GUID / UUID。在不削弱GUID / UUID随机性的情况下,唯一的方法是在16字节的GUID / UUID前加上无符号整数(这将使您的标识符数据为20字节或更多,具体取决于您的整数)。只需生成一个GUID / UUID,然后增加整数。

答案 3 :(得分:0)

这是一个 Linux 示例。 Linux 有一个用于生成 uuid 的头文件,uuid.h。对于我的 Ubuntu 20.x 操作系统,uuid.h 头文件在 /usr/include/uuid/ 中。

/* uuid.c
 * 
 * Defines function uuid
 *
 * Print a universally unique identifer, created using Linux uuid_generate.
 *
 * 
 * Compile
 *
 * gcc uuid.c -o uuid -luuid -Wall -g
 *
 *
 * Run
 * 
 * ./uuid
 * 
 *
 * Debug
 *
 * gdb uuid
 * b main
 * r
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <uuid/uuid.h>

char* uuid(char out[UUID_STR_LEN]){
  uuid_t b;
  uuid_generate(b);
  uuid_unparse_lower(b, out);
  return out;
}

int main(){
  char out[UUID_STR_LEN]={0};
  puts(uuid(out));
  return EXIT_SUCCESS;
}