1

Consider the following array of "strings" in C:

const char* const animals[] =
{
    "",
    "Cat",
    "Dawg",
    "Elephant",
    "Tiger",
};

Is it possible to obtain:

  1. The number of elements (char pointers) in the animals array?

  2. The length of each array member, ie. size = 1 for element 0, size = 4 for element 1 and so on?

I tried using sizeof of course, but it doesnt seem to return anything that makes sense. I think it should be possible for the precompiler to figureout the amount of elements in the array as well as size of each element. For the latter, one could serach of \0 character as well do define length. I wonder however why I cant get proper array size (ie. number of elements in animals array) when using sizeof?

I would appreciate all suggestions.

Edit:

  1. Yes I meant preprocessor, not precompiller, sorry.

  2. Why do I need this functionality? I am parsing incoming strings from a serial port. I need to figure out either the received string matches any string in my preconfigured table. If it does, I need the index of that item. I need the searching algorithm to be fast. Because of that, I first want to check the string size and all bytes after that, only if size matches. Because of that I thought maybe the length of each string is known at compile time.

This is my current checking function:

static int32_t  getStringIndex(const uint8_t* const buf, const uint32_t len)
{
    if (!len)
        return -1;

    int32_t arraySize = sizeof(animals) /  sizeof(animals[0]);
    uint32_t elementSize;

    // The algorithm 1st checks if the length matches. If yes, it compares the strings.
    for (int32_t i = 0; i < arraySize; i++)
    {
        elementSize = strlen(animals[i]);

        if (elementSize == len)
        {
            if (0 == memcmp(animals[i], buf, len))
            {
                return i;
            }
        }
    }

    return -1;
}

I dont use strcmp because buf doesnt have \0 at the end.

9
  • You can use sizeof(animals)/sizeof(*animals) to get the number of animals (including the initial, "empty" animals which you probably shouldn't have). You can use strlen(animals[i]) to get the lengths of the individual animal names. Commented Nov 17, 2017 at 8:06
  • There is no such thing as a precompiler. If you mean the preprocessor then the answer is no. The preprocessor only does textual substitution, it doesn't know anything about sizes of variables. Maybe you should tell us why you need to know that. What is your use case? Commented Nov 17, 2017 at 8:16
  • I have edited my question. Commented Nov 17, 2017 at 8:25
  • 1
    You could compute the lengths of the strings in animals once and for all during the initialisation of the program, so you don't need to call strlen over and over. I don't think you can get the length of a string literal in an array (e.g. sizeof(animals[2]) won't be the length of the strig but the size of a pointer). Commented Nov 17, 2017 at 8:36
  • Thats a good thought actually. Commented Nov 17, 2017 at 8:37

3 Answers 3

2
  1. sizeof animals / sizeof *animals (total size in bytes divided by the size of a single element)

  2. strlen(animals[0]) + 1 (the string length doesn't include the 0 terminator)

Sign up to request clarification or add additional context in comments.

5 Comments

Is there any way to know the size of each element in precompiler?
@Bremen sizeof gives a compile-time constant except when used on a variable-length array.
Thats why I was wondering either the precompiler knows how long are each members since its a const?
@Bremen I'm not sure what you mean by "precompiler". If you mean the preprocessor, no, but you could just use sizeof in the expansion of a macro. (if you have more questions, either edit your question if it's very closely related -- or ask a new question)
Yes, I meant preprocessor, sorry. Thank you.
2
sizeof animals / sizeof animals[0]

Returns the number of elements in the array.

And also you can use strlen() to get length of each of the elements of the array.

From standard §7.24.6.3

The strlen function returns the number of characters that precede the terminating null character.

Also sizeof is an operator.

From standard §6.5.3.4

Another use of the sizeof operator is to compute the number of elements in an array:

     sizeof array / sizeof array[0]

Comments

1

You could make use of the preprocessor to build an array of structs containing the length and the pointer to the string like this:

#include <stdio.h>

struct animalentry
{
  int size;
  const char* const name;
};

#define ANIMAL_ENTRY(a) { sizeof a - 1, a },

const struct animalentry animals[] =
{
  ANIMAL_ENTRY("")
  ANIMAL_ENTRY("Cat")
  ANIMAL_ENTRY("Dawg")
  ANIMAL_ENTRY("Tiger")
};

int main()
{
  for (int i = 0; i < sizeof animals / sizeof animals[0]; i++)
  {
    printf("Name = %s, length = %d\n", animals[i].name, animals[i].size);
  }  
}

The output will be:

Name = , length = 0
Name = Cat, length = 3
Name = Dawg, length = 4
Name = Tiger, length = 5

This should be easy to adapt to your getStringIndex function.

3 Comments

In your case, since name is a const char* and not a const char* const, wont it be stored in RAM instead of FLASH?
@Bremen I don't know, that's specific to your platform, but of course you can adapt this to your needs and add the second const.
Yes, this is definitely the easiest to implement solution. Already implemented and working. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.