I was wondering if it was okay to pass around/return structs holding statically allocated arrays in C++. For example:
typedef struct t{
char name[32];
int id;
}t;
t foo(char name[]){
t my_t = {name, 0};
return my_t;
}
int main(){
t main_t = foo("a struct");
printf("%s", main_t.name); //is this safe to access?
return 0;
}
When it returns the struct by value, I guess it doesn't copy the array name, only the pointer to it.
Edit: Just to clear up some things. I do know that char *var is equal to char var[] in function arguments. I wrote this code up really quickly without even testing it. I know it is definitely not the best code in the world and I wouldn't advice anybody to use it in real life.
Ideally I would allocate the struct dynamically and pass around a pointer, however, I am teaching a person to program in C/C++. It is for a national exam which doesn't require a person to know dynamic allocation or pointers for that matter, that is why * are not really used at all.
The question is really about whether it is okay to return a struct holding a statically allocated array.
Shall we use this piece of code instead:
#include <iostream>
struct t{
char name[32];
int id;
};
t foo(int id){
t my_t;
my_t.id = id;
for(char i = 0; i < 31; i++){
my_t.name[i] = 'a';
}
my_t.name[31] = '\0';
return my_t;
}
int main(){
t main_t = foo(0);
std::cout << main_t.name; //is this safe to access?
return 0;
}
It can be done.
But it shouldn't be done: alternatives are std::string and std::array. You get your copy, allocation, deallocation etc... for free!
struct t {
std::string name;
int id;
std::array<int, 10> integers;
};
...
t main_t = {"a struct"};
main_t.integers[5] = 5;
t copy = main_t;
assert( copy.name == "a struct" );
assert( copy.id == 0 );
assert( copy.integers[5] == 5 );
There is no static array in your code.
When you return a t instance by value, it will copy the contents of the array.
The problem is with how you're initializing the t instance, not with how you're returning it.
Change this:
t my_t = {name,0};
To this:
t my_t = {0};
strncpy(my_t.name,name,sizeof(my_t.name)-1);
Or to this, if you want to avoid the use of library functions:
int i;
t my_t;
for (i=0; i<sizeof(my_t.name)-1 && name[i]!=0; i++)
my_t.name[i] = name[i];
my_t.name[i] = 0;
my_t.id = 0;
You've an error in your program; you're trying to copy a pointer to an array, instead you should copy the contents pointed to by the pointer into the array. It should be like this
#include <algorithm>
#include <cstring>
struct t
{
char name[32];
int id;
};
t foo(const char *name)
{
t my_t = {};
const size_t len = std::strlen(name);
const size_t max_len = sizeof(t::name) / sizeof(t::name[0]) - 1u;
std::copy(name, name + std::min(len, max_len), my_t.name);
return my_t;
}
int main()
{
t main_t = foo("a struct");
printf("%s", main_t.name);
}
As for your question
I was wondering if it was okay to pass around/return structs holding static arrays in C++
Yes, it's ok, the whole struct will get copied (or moved, depending on the type) to the variable at the calling end.
It's OK to pass around structs that contain arrays. However, this line doesn't do what you think it does:
t my_t = {name, 0};
Using designated initializer syntax, it would be equivalent to:
t my_t = { .name[0] = name; .name[1] = 0; };
The first member of t is an array with 32 elements, so the first 32 initializers are applied to those 32 chars. Unless you use some more braces, but you still need one initializer per element, there's no magic way to get a strcpy out of brace-enclosed initializers.
You should get a compiler error about initializing a char with a pointer.
Related
I am trying to solve a coding question that requires the results be returned using a given struct. The struct is defined as:
struct Answer
{
const char* const* lastNames;
unsigned numberOfPeople;
}
Where the lastNames is a pointer to last names that are each terminated by a non-alpha char. I can not seem to find any way to convert the vector of strings that I am using to compile all the last names into a variable that I can assign to lastNames. I have tried making a single string with all the last names and assigning it with c_str() like so:
Ans->lastName = allNames.c_str(); but this gives me an error. Due to the limitations of the question I am unable to change the struct variable to anything else. How can I assign a string to a const char* const*
The structure being used effectively uses a C-style approach to defining a variable sized array of pointers to char (with const sprinkled over it). You’ll need storage for both the array of char const* as well as the entities pointed to. Here is how you could build it from a std::vector<std::string>:
std::vector<std::string> strings = somehow_compute_the_strings();
std::vector<char const*> array;
for (std::string const& s: strings) {
array.push_back(s.c_str());
}
Answer answer = { array.data(), array.size() };
Of course, you can’t return answer without the pointer inside pointing to stale data: you’d need to keep the two std::vectors alive. Potentially these two objects could be made members of an object the function is called on. To actually return an object of type Answer without a place to hold on to the std::vectors you could allocate the relevant entities and accept that the result will yield a memory leak unless the caller can clean the result up.
You can't just cast stuff. struct Answer is expecting a char**, so you are going to have to build it and keep it valid as long as the struct Answer is in use. At least they were kind enough to let us know they don't intend to modify it or mess with cleaning up the memory, since it takes "const char * const *".
#include <iostream>
#include <vector>
#include <string>
#include <assert.h>
typedef std::vector<std::string> VectorOfStrings_type;
struct Answer
{
const char* const* lastNames;
unsigned numberOfPeople;
};
class AnswerWrapper
{
private:
// construct and maintain memory so the pointers in the Answer struct will be valid
char ** lastNames;
unsigned int numberOfPeople;
public:
AnswerWrapper(const VectorOfStrings_type &input){
numberOfPeople = input.size();
// create the array of pointers
lastNames = static_cast<char**>(
malloc(numberOfPeople * sizeof(char*))
);
// create each string
for (unsigned int i = 0; i < numberOfPeople; ++i){
const std::string &name = input[i];
// allocate space
lastNames[i] = static_cast<char*>(
malloc(name.size() + 1)
);
// copy string
strncpy(lastNames[i], name.data(), name.size());
// add null terminator
lastNames[i][name.size()] = '\0';
}
}
operator Answer (){
return Answer{ lastNames, numberOfPeople };
}
~AnswerWrapper(){
// critcally important, left as an exercise
assert(0);
}
};
void SomeFunctionWhichUsesAnswer(Answer a){
// presumably you have some legacy C code here
// but here's a quick and easy demo
for (unsigned int i = 0; i < a.numberOfPeople; ++i)
std::cout << a.lastNames[i] << std::endl;
}
int main() {
// Here is your vector of strings
VectorOfStrings_type myData { "custom formatted data goes here", "and more here", "and again" };
// You must construct a buffer for the "Answer" type, which must remain in scope
AnswerWrapper temp{ myData };
// AnswerWrapper is currently in scope, so inside this function, the pointers will be valid
SomeFunctionWhichUsesAnswer(temp);
}
Also, I noticed that the strings in Answer are not referred to as null terminated. That is a separate issue you can take care of.
A const member variable can only be assigned in the constructor.
if you can add to the struct, define a constructor, and use the : lastname(value) syntax; or use the struct Answer myVar{value,number}; initialization, right where you declare your instance.
Another - ugly, dangerous, and frowned upon - alternative is a cast: (char**) lastname = value;, or in C++ syntax reinterpret_cast<char**>(lastname) = value.
If someone is teaching you either of those approaches, change the teacher.
I wondering what the best solution is for a structure with variable length array for one of the fields. I've done a bunch of research and I haven't seen a clear answer yet.
I've been playing with the below code and trying to get the varField to be set to an array the size of 10 bytes.
typedef struct TestStruct{
int size;
unsigned char varField[1];
}
I have tried doing zero sized array and that gives me a compile error.
I also tried something like this and it gave me a compile error.
int size= 10;
struct TestStruct*test = malloc(sizeof(struct TestStruct) + (size- 1));
test->size= size;
Thank you so much for help.
The preferred way is to use the dynamically re-sizable std::vector. This class has the rule of five built in.
struct TestStruct {
std::vector<unsigned char> varField;
}
If you're allergic to the standard library, you could use:
unsigned char *varfield;
And supply the necessary constructors/destructors.
If you are implementing messages, a better solution is to set up a hierarchy:
struct Message_Base
{
unsigned int message_length_in_bytes;
unsigned int message_id;
virtual Checksum_Type calculate_checksum(void) = 0;
virtual bool send_message(Receiver& r) = 0;
virtual bool receive_message(Sender& s) = 0;
virtual void process_message(void) = 0;
};
Each child class would be a different message with possible different lengths. Some possible common methods to all message are listed.
This is how to implement using Object Oriented and C++.
The class C language implementation is to declare a zero length array at the end for the message's unique data.
You look like you want a std::vector<unsigned char>:
struct TestStruct{
std::vector<unsigned char> varField;
}
and you get the size with:
ts.varField.size();
You can't. In C++ dynamic size arrays are illegal. The size of an array must be a compile time constant expression.
The options you have basically are
Use an STL container like std::vector or the like. The benefits are that they also take care of memory allocation and deallocation for you.
Use a pointer in your struct and allocate the memory for it dynamically. Don't forget to use delete[] instead of just delete!
In most compilers, the following will work:
template<unsigned N>
struct TestStruct {
unsigned size = N;
unsigned char varField[N];
};
struct ITestStruct {
unsigned size;
unsigned char varField[1]; // variable
};
template<unsigned N>
ITestStruct* make_test_struct() {
return reinterpret_cast<ITestStruct*>(new TestStruct<N>());
};
ITestStruct* make_test_struct( unsigned n ) {
char* buff = new char[ sizeof(ITestStruct)+n-1 ];
ITestStruct* retval = reinterpret_cast<ITestStruct*>(buff);
retval->size = n;
return retval;
}
If you replace char with another non-POD type, things will get hairy.
#include<iostream>
#include<string>
using namespace std;
int main(void) {
struct STRCT {
int num;
string str1,
arrStr1[],
str2,
arrStr2[];
};
int a;
string b[2],
c[3],
d,
e;
a = 10;
b[0] = "hello";
b[1] = "world";
c[0] = "stack";
c[1] = "over";
c[2] = "flow";
d = "random";
e = "text";
//how do i intialize the arrays (arrStr1[] and arrStr2[]) in aStruct along with the rest of items?
//is it like this?
//i want aStruct[] to be an array and i want its size to be declared from the start to later be filled with vals
STRCT aStruct[2];
//then later in the program i want to assign aStruct[] vals
aStruct[0] = {a, //int
d, //string
{b}, //string[]
e, //string
{c}}; //string[]
}
so basically i want to make a struct array with arrays inside then get the proper vals and then assign the proper vals to the arrays inside the struct array. thank you very much in advance for the help
Array declarations in your struct are simply illegal. C++ does not support size-less array declarations as class members. And even if some C++ compiler supports a C99-style "struct hack" declaration, only one size-less array is allowed and the array must be the last member of the struct.
You want to have arrays inside your struct - you have to give them specific compile-time sizes. Without specific compile time size you'll have to use pointers or std::vector.
In your example b has size 2 and c has size 3. You can declare your struct with the same sizes
struct STRCT {
int num;
string str1, arrStr1[2], str2, arrStr2[3];
};
and then initialize it as follows
STRCT aStruct[2] =
{
{
a,
d,
{ b[0], b[1] },
e,
{ c[0], c[1], c[2] }
}
// The rest of the array is value-initialized
};
That's just as far as you can get with ordinary arrays. It you want something more flexible, embedding arrays straight into the struct won't help you here. Either construct the necessary memory structures manually or use std::vector.
In C++ this is illegal
string arr[2] = {"This","is"};
string arr1[2];
arr1 = arr;
There is nothing like "copy an entire array into another array". The array elements must be copied individually.
Second you cant declare arrays of unknown size
You can modify your struct declaration by declaring string array of fixed size and do this
for(int i =0; i< 2; i++)
{
aStruct[i].num = a;
aStruct[i].str1= d;
for(int j=0;j<2;j++)
{
arrStr1[i] = b[i];
}
aStruct[i].str2= e;
for(int k=0;k<3;k++)
{
arrStr2[i] = c[i];
}
}
I suggest instead of string arrStr1[] ,string arrStr2[] , b[2] and c[2] make use of std::vector. That will help you in avoid hard coding the conditions in for loop.
I am passing an array to a function, and i am initializing it globally with some values.
I am using empty string in end of array to determine the array length.
Now, Is there some way to automatically initialize the array to have extra empty item in the end of it, so i have no chances to forget it from there? Just like the char[] works, it adds extra null to the end IIRC.
Here is my code what im using now:
struct twostrings {
string s1, s2;
};
twostrings options[] = {
{"text1", "more text1"},
{"text2", "more text2"},
{"text3", "more text3"},
{""}, // tells that the array ends here
}
int get_len(twostrings opt[]){
int p = 0;
while(1){
if(opt[p].s1 == ""){
return p;
}
p++;
// now here is a possibility to go in infinite loop if i forgot the empty string.
// currently i have a code here that checks if p > 10000 and gives error message to me if i manage to forget that empty string in accident.
}
return p;
}
void dosomething(twostrings options[]){
int len = get_len(options);
for(int p = 0; p < len; p++){
// do stuff
}
}
int main(){ // yes its not valid written main function. dont bother about it.
dosomething(options);
}
Passing around C arrays is not very idiomatic in C++. Try using a std::vector instead:
#include <vector>
#include <string>
struct twostrings {
std::string s1, s2;
};
typedef std::vector<twostrings> option_type;
twostrings options[] = {
{"text1", "more text1"},
{"text2", "more text2"},
{"text3", "more text3"}
};
int get_len(const option_type& options){
return options.size();
}
void dosomething(const option_type& options){
int len = get_len(options);
for(int p = 0; p < len; p++){
// do stuff
}
}
int main() { // This main function is perfectly fine!
option_type opt_vector(options, options + (sizeof options / sizeof options[0]));
dosomething(opt_vector);
}
Unforunately, you're not correct. The char array does not end automatically in a null, this is only a side effect of assigning it with a string literal (which has the automatic null at the end).
char x[] = "ABC"; // size 4, contains A, B, C, \0.
char x[] = {'A','B','C'}; // size 3, contains no terminating null.
So the short answer is no, there's no way to automatically end arrays with an automatic entry. There are a bunch of other options though, such as STL vectors which have other means of determining when you've reached the end. In C++0x there'll probably (IIRC) be a way to initialize the vector just like you'd like.
HTH.
EDIT:
Personally, I prefer to add the extra 0 at the end of the array myself, but I suppose there are ways to work around it using macros.
#define ARRAY(...) {__VA_ARGS__, {0}}
and use it like so
struct foo { char* x; char* y; }
struct foo x[] = ARRAY({"abc", "xyz"}, {"def","uvw"});
I have no idea if this works (and I have no preprocessor handy), and as I said, personally I don't like it. It also requires the first element in the struct to be something which can be assigned 0 to mark the end of the array.
Of course, this forces you to remember to wrap it in the macro call, which is pretty much as bad as forcing you to remember to terminate the array.
EDIT:
I just had a chance to test this and it works. Turns out variadic macros are, so far anyway, C only. However some (most?) C++ compilers support them anyway, a quick search turned up g++ and visual studio. Still I wouldn't favor this approach, I just added it for completeness.
Pass the length or the end instead of using a sentinel:
template<class T, int N>
int len(T (&)[N]) { // exists in a more general form as boost::size
return N;
}
typedef std::pair<std::string, std::string> twostrings;
// std::pairs have first and second members of the given types
void dosomething(twostrings options[], int size);
// call as: dosomething(array, len(array));
# or:
template<class T, int N>
T* end(T (&a)[N]) { // exists in a more general form as boost::end
return a + N;
}
void dosomething(twostrings* options_begin, twooptions* options_end);
// call as: dosomething(array, end(array));
// usage example:
void dosomething(twostrings* options_begin, twooptions* options_end) {
// you might name the parameters just 'begin' and 'end'
for (; options_begin != options_end; ++options_begin) {
// the 'begin' var advances through the entire sequence
// use for (twostrings* current = options_begin; current != options_end; ++current)
// if a separate copy is required
cout << options_begin->first << ": " << options_begin->second << '\n';
}
}
Note the [begin, end) iterator pattern (that's inclusive begin, exclusive end) is common in the stdlib (e.g. look at std::sort from <algorithm>).
This is a good halfway measure between arrays and containers such as std::vector, and allows you to keep the easy initialization syntax you have now (C++0x gives you that same syntax with containers such as std::vector, but 0x is not quite yet ready).
Don't use C style arrays in C++, they're just not worth the effort compared to vector.size(). You should use a boost::array<twostrings, length> for a static array.
Hell, you should probably just not use a static value.
There are better ways of finding array lengths. You can use:
1. sizeof(options) / sizeof(twostrings);
2. sizeof(options) / sizeof(options[0]);
3. std::vector<twostrings> options;
options.size();
4. ARRAYSIZE(options); (windows only)
Btw, if(opt[p].s1 == "") is checking 2 const char * pointers for equality, not 2 strings. Although compiller usualy optimizes equal string constants to point to one place, it is still an error.
You should use a NULL sentinell as it was adviced by Svisstack earlier.
edit: Proof
#include <stdio.h>
const char *one = "the string";
void main(){
const char *other = "the string";
printf("adress of 'one' = %x, it contains \"%s\"\n", one, one);
printf("adress of 'other' = %x, it contains \"%s\"\n", other, other);
if(one == other){
printf("one == other\n", one);
} else {
printf("one != other\n", one);
}
}
Output:
k:\temp>cl test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
/out:test.exe
test.obj
k:\temp>test.exe
adress of 'one' = 3d8140, it contains "the string"
adress of 'other' = 3d814c, it contains "the string"
one != other
I want to dynamically allocate a C struct:
typedef struct {
short *offset;
char *values;
} swc;
Both 'offset' and 'values' are supposed to be arrays, but their size is unknown until runtime.
How can I dynamically allocate memory for my struct and the struct's arrays?
swc *a = (swc*)malloc(sizeof(swc));
a->offset = (short*)malloc(sizeof(short)*n);
a->values = (char*)malloc(sizeof(char)*n);
Where n = the number of items in each array and a is the address of the newly allocated data structure. Don't forget to free() offsets and values before free()'ing a.
In C:
swc *s = malloc(sizeof *s); // assuming you're creating a single instance of swc
if (s)
{
s->offset = malloc(sizeof *(s->offset) * number_of_offset_elements);
s->values = malloc(sizeof *(s->values) * number_of_value_elements);
}
In C++:
try
{
swc *s = new swc;
s->offset = new short[number_of_offset_elements];
s->values = new char[number_of_value_elements];
}
catch(...)
{
...
}
Note that in C++, you might be better off using vectors as opposed to dynamically allocated buffers:
struct swc
{
std::vector<short> offset;
std::vector<char> values;
};
swc *a = new swc;
Question: is values supposed to be an array of individual characters or an array of strings? That would change things a bit.
EDIT
The more I think about it, the less satisfied I am with the C++ answer; the right way to do this sort of thing in C++ (assuming you need dynamically allocated buffers as opposed to vectors, which you probably don't) is to perform the memory allocation for offset and values as part of a constructor within the struct type, and have a destructor deallocate those elements when the struct instance is destroyed (either by a delete or by going out of scope).
struct swc
{
swc(size_t numOffset = SOME_DEFAULT_VALUE,
size_t numValues = SOME_OTHER_DEFAULT_VALUE)
{
m_offset = new short[numOffset];
m_values = new char[numValues];
}
~swc()
{
delete[] m_offset;
delete[] m_values;
}
short *m_offset;
char *m_values;
};
void foo(void)
{
swc *a = new swc(10,20); // m_offset and m_values allocated as
// part of the constructor
swc b; // uses default sizes for m_offset and m_values
...
a->m_offset[0] = 1;
a->m_values[0] = 'a';
b.m_offset[0] = 2;
b.m_values[0] = 'b';
...
delete a; // handles freeing m_offset and m_values
// b's members are deallocated when it goes out of scope
}
You have to do it seperately. First allocate the struct, then the memory for the arrays.
In C:
swc *pSwc = malloc(sizeof(swc));
pSwc->offset = malloc(sizeof(short)*offsetArrayLength);
pSwc->values = malloc(valuesArrayLength);
In C++, you shouldn't be doing anything like that.
In C:
typedef struct
{
short *offset;
char *values;
} swc;
/// Pre-Condition: None
/// Post-Condition: On failure will return NULL.
/// On Success a valid pointer is returned where
/// offset[0-n) and values[0-n) are legally de-refrancable.
/// Ownership of this memory is returned to the caller who
/// is responsible for destroying it via destroy_swc()
swc *create_swc(unsigned int size)
{
swc *data = (swc*) malloc(sizeof(swc));
if (data)
{
data->offset = (short*)malloc(sizeof(short)*n);
data->values = (char*) malloc(sizeof(char) *n);
}
if ((data != NULL) && (size != 0) && ((data->offset == NULL) || (data->values == NULL)))
{
// Partially created object is dangerous and of no use.
destroy_swc(data);
data = NULL;
}
return data;
}
void destroy_swc(swc* data)
{
free(data->offset);
free(data->values);
free(data);
}
In C++
struct swc
{
std::vector<short> offset;
std::vector<char> values;
swc(unsigned int size)
:offset(size)
,values(size)
{}
};
You will need a function to do this.
Something like (my C/C++ is rusty)
swc* makeStruct(int offsetCount, int valuesCount) {
swc *ans = new swc();
ans->offset = new short[offsetCount];
ans->values = new char[valuesCount];
return ans;
}
myNewStruct = makeStruct(4, 20);
Syntax may be a bit off but that is generally what you are going to need. If you're using C++ then you probably want a class with a constructor taking the 2 args instead of the makeStruct but doing something very similar.
One thing to add to the many correct answers here: you can malloc an over-sized structure to accommodate a variable sized array in the last member.
struct foo {
short* offset;
char values[0]
};
and later
struct *foo foo1 = malloc(sizeof(struct foo)+30); // takes advantage of sizeof(char)==1
to get room for 30 objects in the values array. You would still need to do
foo1->offsets = malloc(30*sizeof(short));
if you want them to use the same size arrays.
I generally wouldn't actually do this (maintenance nightmare if the structure ever needs to expand), but it is a tool in the kit.
[code here in c. You'll need to cast the malloc's (or better use new and RAII idioms) in c++]
swc* a = malloc(sizeof(*a));
a->offset = calloc(n, sizeof(*(a->offset)));
a->values = calloc(n, sizeof(*(a->values)));
You should not cast void* in c... in c++ you must!
Use malloc function or calloc to allocate memory dynamically .
and search it on google to get examples.
The calloc function initializes allocated memory to zero.
Since nobody has mentioned it yet, sometimes it is nice to grab this chunk of memory in one allocation so you only have to call free() on one thing:
swc* AllocSWC(int items)
{
int size = sizeof(swc); // for the struct itself
size += (items * sizeof(short)); // for the array of shorts
size += (items * sizeof(char)); // for the array of chars
swc* p = (swc*)malloc(size);
memset(p, 0, size);
p->offset = (short*)((char*)swc + sizeof(swc)); // array of shorts begins immediately after the struct
p->values = (char*)((char*)swc + sizeof(swc) + items * sizeof(short)); // array of chars begins immediately after the array of shorts
return p;
}
Of course this is a bit more difficult to read and maintain (especially if you dynamically resize the arrays after it is first allocated). Just an alternative method I've seen used in a number of places.
Most of the answers are correct. I would like to add something that you haven't explicitly asked but might also be important.
C / C++ arrays don't store their own size in memory. Thus, unless you want offset and values to have compile-time defined values (and, in that case, it's better to use fixed-size arrays), you might want to store the sizes of both arrays in the struct.
typedef struct tagswc {
short *offset;
char *values;
// EDIT: Changed int to size_t, thanks Chris Lutz!
size_t offset_count;
size_t values_count; // You don't need this one if values is a C string.
} swc;
DISCLAIMER: I might be wrong. For example, if all offsets of all swc instances have the same size, it would be better to store offset_count as a global member, not as a member of the struct. The same can be said about values and values_count. Also, if values is a C string, you don't need to store its size, but beware of Schlemiel the painter-like problems.
You want to use malloc to allocate the memory, and probably also sizeof() to allocate the correct amount of space.
Something like:
structVariable = (*swc) malloc(sizeof(swc));
Should do the trick.
In addition to the above, I would like to add freeing up the allocated memory as below.,
typedef struct {
short *offset;
char *values;
} swc;
swc* createStructure(int Count1, int Count2) {
swc *s1 = new swc();
s1->offset = new short[Count1];
s1->values = new char[Count2];
return s1;
}
int _tmain(int argc, _TCHAR* argv[])
{
swc *mystruct;
mystruct = createStructure(11, 11);
delete[] mystruct->offset;
delete[] mystruct->values;
delete mystruct;
return 0;
}
**If** you will not be resizing the arrays, then you can get away with a single call to malloc().
swc *new_swc (int m, int n) {
swc *p;
p = malloc (sizeof (*p) + m * sizeof (p->offset[0]) + n * sizeof (p->values[0]);
p->offset = (short *) &p[1];
p->values = (char *) &p->offset[m];
return p;
}
You can then free it with a single call to free().
(In general, there are alignment considerations to take into account, but for an array of shorts followed by an array of chars, you will be fine.)