0

This question has totally confused me-

I have an array(fixed size):

unsigned int i_block[15];

I have a string(length <= 60):

"path/to/bla/is/bla"

How would I go about storing the characters of the string in the space for the array? I was thinking about perhaps using memset, but I have no idea if that would even work?

For Reference: "If the data of a file fits in the space allocated for pointers to the data, this space can conveniently be used. E.g. ext2 stores the data of symlinks (typically file names) in this way, if the data is no more than 60 bytes ("fast symbolic links")."

from

Source

user126885
  • 157
  • 1
  • 2
  • 10
  • `I was thinking about perhaps using memset, but I have no idea if that would even work?` - Well, `memset` certainly won't, since it's for... setting memory to a uniform byte value. `memcpy` might. Try it. Hint: the Standard allows any type to be written using, and have its representation reinterpreted via, a `char *` pointer. – underscore_d Aug 01 '16 at 15:31
  • 3
    You'd probably have better luck with `memcpy` than `memset`. – Fred Larson Aug 01 '16 at 15:32
  • 5
    Do you know for a fact that `sizeof(int) >= 4` on your platform? – Fred Larson Aug 01 '16 at 15:33
  • memcpy(i_block, str, strlen(str)) or memcpy(i_block[0], str, strlen(str)). – user126885 Aug 01 '16 at 15:34
  • That's definitely some code. What's your point? In this case, both variants of `i_block` represent pointers to the same address, and since `memcpy` converts them to `void *`, it doesn't care that one was originally a pointer-to-array but the other was - or _would be_ had you included the missing operator `&` - originally a pointer-to-element. – underscore_d Aug 01 '16 at 15:34
  • 2
    If the string is known at compile time you better use `sizeof` instead of `strlen` to be faster. – cadaniluk Aug 01 '16 at 15:35
  • 2
    first one or the second but `memcpy(&i_block[0], str, strlen(str)+1).` – LPs Aug 01 '16 at 15:35
  • I know that the size of an unsigned int is 4 bytes – user126885 Aug 01 '16 at 15:36
  • 1
    Don't forget to account for a null terminator, or some way of knowing where your string ends. – Fred Larson Aug 01 '16 at 15:36
  • @LPs if I have a strlen of 60 wont that be problematic? Considering that the area is 60 bytes? – user126885 Aug 01 '16 at 15:39
  • 1
    It only depends on what you want to store: if you want to store a C-string you must copy the null terminator. If only characters of C-string matter you can avoid the +1. In other words you can store a C-String of `59` chars or `60` chars. – LPs Aug 01 '16 at 15:40
  • 2
    if `sizeof(unsigned int) == 4` and length = `60`, you don't leave space for the trailing `'\0'` – David Ranieri Aug 01 '16 at 15:41
  • You could potentially use space padding. – Fred Larson Aug 01 '16 at 15:42
  • @LPs I am only storing the characters not the string. – user126885 Aug 01 '16 at 15:46
  • 2
    So `memcpy(&i_block[0], str, strlen(str));` it's correct – LPs Aug 01 '16 at 15:47
  • Your comment says " I am only storing the characters not the string", post's title says "Storing a string ..." and body asks "How would I go about storing the string " . Suggest retracting the comment or fixing title/body. – chux - Reinstate Monica Aug 01 '16 at 16:06

1 Answers1

2

This code assumes that the int type uses 4 bytes, hence 15 int use 60 bytes.

You can store the string this way:

size_t len = strlen(str);
if (len <= sizeof i_block) {
    memset(i_block, 0, sizeof i_block);
    memcpy(i_block, str, len);
}

The array should be filled with '\0' for cleanliness and to provide a way to tell the length of the string. The above code is simple and readable. You could copy the string and just set the remainder of the buffer to 0 with a slightly less readable call to memset.

Note that if the string length is 60, there will be no trailing '\0' at the end of the array. The string should be retrieved carefully to account for this limitation.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 2
    I think this is workable. But be aware that there's no null terminator at maximum length. That case will have to be handled when accessing the string later. – Fred Larson Aug 01 '16 at 15:44
  • @FredLarson I would prefer to handle the case later on. – user126885 Aug 01 '16 at 15:50
  • 1
    @FredLarson: good point, I amended the answer. Incidentally, this is one of the rare occasions where the semantics of `strncpy` are appropriate. Nevertheless, I shall not condone using this error prone function. – chqrlie Aug 01 '16 at 15:50
  • @chqrlie is the memset with null values required? Are there any issues if dont set the null values? – user126885 Aug 01 '16 at 15:50
  • 1
    @user126885: Yes, unless you want to have gibberish at the end of your string. – Fred Larson Aug 01 '16 at 15:52
  • @FredLarson completely forgot about that. Thanks – user126885 Aug 01 '16 at 15:54
  • Alternative to `memset(),memcpy()`: `strncpy(i_block, str, sizeof i_block);` – chux - Reinstate Monica Aug 01 '16 at 16:01
  • @chux: correct, but promoting the use of this function, even when it is appropriate, is highly debatable. This function was indeed created for a very similar purpose for an archaic file system, back in 1973. Its track record of misuse and semantical confusion warrants its removal from any readable code. – chqrlie Aug 01 '16 at 16:11
  • @chqrlie You are saying that you have a problem with people using `strncpy()`, am I reading that right? Could you explain why that is? In almost all cases this function does exactly what it should and is the fastest to achieve this functionality. – Meik Vtune Aug 01 '16 at 17:05
  • @MeikVtune: Very few programmers know what this function does. Most believe it to be a *safer version of strcpy*, which it is not. Even in the above example, it would not be the fastest way to achieve the result since we already know the length of the string, `memcpy`+`memset` could be faster. There are countless articles on how error prone this function is. Try this one: https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/ and this: http://blog.liw.fi/posts/strncpy/ and this: https://news.ycombinator.com/item?id=9637822 – chqrlie Aug 01 '16 at 19:26
  • @MeikVtune: *In almost all cases this function does exactly what it should and is the fastest to achieve this functionality.* really? I suspect you do not know precisely what this function does. It is almost never the right tool for the job. It is vastly misused. The posted answer is one of the very rare cases where the semantics of strncpy is a good match, but using it even in these rare occasions has poor pedagogical value. There is one thing the casual reader should learn about this function: **never ever use it** – chqrlie Aug 01 '16 at 19:32
  • @chqrlie "The fastest" was not about the implementation. It was purely about 'waste-of-time', because if you don't use `strncpy()` you'd have to either write something yourself or check other libraries for that functionality. – Meik Vtune Aug 01 '16 at 19:45
  • @chqrlie So i've read parts of your links. In the end your only problem with that function is that there is no guarantee for NUL-termination and that you may write too much. Just because the function forces you to think about this(once, because you can simply write a wrapper that handles the problems) you dislike it, definitely not worth saying "never use it". – Meik Vtune Aug 01 '16 at 19:50
  • @MeikVtune: I'm afraid you haven't read enough bogus code... I personally have no problem to use this function correctly, but I have seen so many programmers misuse it, causing subtile bugs in production code, that I feel very strongly against using it at all. Your explanation is beside the point. You hint that one can write a wrapper to *handle the problem*... There is no such problem in the case above, while for the much more common case of string copy with truncation, a tailor made function such as BSD's `strlcpy()` is a much better option, and sound advice. – chqrlie Aug 01 '16 at 21:12