如何使用C中先前定义的常量定义静态const?

时间:2016-03-26 16:31:41

标签: c constants

static const vs #define#defining constants in C++并未对此做出完全回答。

当我在C中进行大量编程时,ANSI C是全新的。我们大多使用#define来定义常量。我已经意识到这不再是最佳做法(https://codereview.stackexchange.com/questions/123848/verifying-e-mail-address-in-c/123856#123856)。

使用#define我可以使用先前的常量来定义当前常量,例如

#define EMAIL_CHAR_ARRAY_SIZE 40
#define GOOD_EMAIL_ADDRESS  1
#define BAD_EMAIL_ADDRESS 0
#define MIMIMUM_USER_NAME_LENGTH 1
#define AT_SIGN_LENGTH 1
#define DOT_LENGTH 1
#define MINIMUM_DOMAIN_LENGTH 1
#define MINIMUM_ROOT_DOMAIN_LENGTH 2
#define MINIUMUM_EMAIL_LENGTH MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH

我有一个程序(下面),我试图使用静态const而不是#define,但是当我尝试使用前面的常量使用静态const时,常量MINIUMUM_EMAIL_LENGTH不会编译。有没有办法在静态const TYPE声明中使用先前定义的常量?

const_testemail.c:12:5: error: initializer element is not constant
     static const int MINIUMUM_EMAIL_LENGTH = (MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH);


#include <stdio.h>
#include <string.h>

static const int EMAIL_CHAR_ARRAY_SIZE = 40;
static const int GOOD_EMAIL_ADDRESS  = 1;
static const int BAD_EMAIL_ADDRESS = 0;
static const int MIMIMUM_USER_NAME_LENGTH = 1;
static const int AT_SIGN_LENGTH = 1;
static const int DOT_LENGTH = 1;
static const int MINIMUM_DOMAIN_LENGTH = 1;
static const int MINIMUM_ROOT_DOMAIN_LENGTH = 2;
/*  Doesn't compile 
 *  static const int MINIUMUM_EMAIL_LENGTH = MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH;
 *  */

#define MINIUMUM_EMAIL_LENGTH (MIMIMUM_USER_NAME_LENGTH + AT_SIGN_LENGTH + MINIMUM_DOMAIN_LENGTH + MINIMUM_ROOT_DOMAIN_LENGTH)

int isEmailAddressProper(const char EmailAddress[EMAIL_CHAR_ARRAY_SIZE])
{
    int     EmailAddressIsGood = GOOD_EMAIL_ADDRESS;
    int     LengthOfEmailAddress;
    char    *AtSignLocation, *pos2;
    int     rootDomainLength;

    LengthOfEmailAddress = strlen(EmailAddress);
    if (LengthOfEmailAddress < MINIUMUM_EMAIL_LENGTH)
    {
        printf("The length of the email address is less than the minimum lenght %d\n", MINIUMUM_EMAIL_LENGTH);
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    AtSignLocation = strchr(EmailAddress, '@'); /* get the first instance of @ */
    if (!AtSignLocation)
    {
        printf("There is no @ in the email address\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
        return EmailAddressIsGood;
    }

    if (AtSignLocation == EmailAddress) { /* Is @ the first character? */
        printf("There is no user name in the email address, @ is the first character\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    pos2 = strrchr(EmailAddress, '@'); /* find any other @ */
    if ((pos2) && (AtSignLocation != pos2)) {
        printf("There is more than 1 @ in the email address\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    pos2 = strrchr(EmailAddress, '.'); /* get the last instance of '.' */
    if (AtSignLocation > pos2) /* is . before @ ? */
    {            printf("There is no root domain in the email address\n");
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    pos2++;
    rootDomainLength = LengthOfEmailAddress - ((int)(pos2 - EmailAddress));
    /* if root domain less than length 2 */
    if (rootDomainLength < MINIMUM_ROOT_DOMAIN_LENGTH)
    {
        printf("The root domain length (%d) is less than the minimum length required (%d) in the email address\n", rootDomainLength, MINIMUM_ROOT_DOMAIN_LENGTH);
        EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    }

    return EmailAddressIsGood;
}

void GetAndValidateEmailAddress(char EmailAddress[EMAIL_CHAR_ARRAY_SIZE])
{
    int EmailAddressIsGood = BAD_EMAIL_ADDRESS;
    char TempEmail[EMAIL_CHAR_ARRAY_SIZE];

    while (!EmailAddressIsGood)
    {
        scanf("%39s", TempEmail);
        EmailAddressIsGood = isEmailAddressProper(TempEmail);
        if (!EmailAddressIsGood) {
            printf("The email address is not in the proper format, please re-enter the email address\n");
        }
    }

   strcpy(EmailAddress, TempEmail);
}

main()
{
    char EmailAddress[EMAIL_CHAR_ARRAY_SIZE];

    printf("Please enter the email address\n");
    GetAndValidateEmailAddress(EmailAddress);
    printf("The email address you entered is %s\n", EmailAddress);
}

1 个答案:

答案 0 :(得分:0)

C除了枚举常量(总是类型为int)之外没有符号常量。 #define是一个宏,是 pre 处理器的一部分。它是实际C语言编译之前的文本替换。

const限定变量在语义上仍然是变量。限定符是程序员的保证,他不会更改值。编译器可能依赖此保证。打破合同会调用未定义的行为,但它不一定由运行时环境强制执行。

文件级的静态初始化程序和数组索引需要常量表达式,因此需要输入错误。简而言之,常量表达式必须在编译时产生一个常量值,因此不能使用变量。

请注意,函数中的数组参数存在类似问题。但是在这里你可以使用一个可变长度的数组。但是,您可以使用空长度([])或将长度作为前置参数显式传递;全局变量不起作用:

int isEmailAddressProper(size_t len, const char EmailAddress[len])

C ++是一种具有相似语法/语法的不同语言,即使对于相同的语法也有很多不同的语义。你经常无法将语言知识应用到另一方。