服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言容易被忽视的函数设计原则基础

C语言容易被忽视的函数设计原则基础

2022-11-14 14:01清风自在 流水潺潺 C/C++

C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言.那么C语言函数设计的一般原则和技巧都是怎样的呢,下面带你了解

一、函数设计原则

  • 函数从意义上应该是一个独立的功能模块
  • 函数名要在一定程度上反映函数的功能
  • 函数参数名要能够体现参数的意义
  • 尽量避免在函数中使用全局变量
  • 当函数参数不应该在函数体内部被修改时,应加上 const 声明
  • 如果参数是指针,且仅作输入参数,则应加上 const 声明,如下:

C语言容易被忽视的函数设计原则基础

  • 不能省略返回值的类型
  • 如果函数没有返回值,那么应声明为 void
  • 类型对参数进行有效性检查
  • 对于指针参数的检查尤为重要
  • 不要返回指向“栈内存”的指针
  • 栈内存在函数体结束时被自动释放
  • 函数体的规模要小,尽量控制在 80 行代码之内
  • 相同的输入对应相同的输出,避免函数带有“记忆”功能
  • 避免函数有过多的参数,参数个数尽量控制在 4 个以内
  • 有时候函数不需要返回值,但为了增加灵活性,如支持链式表达,可以附加返回值

C语言容易被忽视的函数设计原则基础

  • 函数名与返回值类型在语义上不可冲突

C语言容易被忽视的函数设计原则基础

下面来欣赏一份优秀的代码:

/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at 
* http://www.eclipse.org/legal/epl-v10.html
* 
* Contributors:
*     IBM Corporation - initial API and implementation
*     Kevin Cornell (Rational Software Corporation)
*******************************************************************************/
/* Eclipse Launcher Utility Methods */
#include "eclipseOS.h"
#include "eclipseCommon.h"
#include "eclipseUtil.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#include <strings.h>
#endif
#define MAX_LINE_LENGTH 256
/* Is the given VM J9 */
int isJ9VM( _TCHAR* vm )
{
	_TCHAR * ch = NULL, *ch2 = NULL;
	int res = 0;
	if (vm == NULL)
		return 0;
	ch = lastDirSeparator( vm );
	if (isVMLibrary(vm)) {
		/* a library, call it j9 if the parent dir is j9vm */
		if(ch == NULL)
			return 0;
		ch[0] = 0;
		ch2 = lastDirSeparator(vm);
		if(ch2 != NULL) {
			res = (_tcsicmp(ch2 + 1, _T_ECLIPSE("j9vm")) == 0);
		}
		ch[0] = dirSeparator;
		return res;
	} else {
		if (ch == NULL)
		    ch = vm;
		else
		    ch++;
		return (_tcsicmp( ch, _T_ECLIPSE("j9") ) == 0);
	}
}
int checkProvidedVMType( _TCHAR* vm ) 
{
	_TCHAR* ch = NULL;
	struct _stat stats;
	if (vm == NULL) return VM_NOTHING;
	if (_tstat(vm, &stats) == 0 && (stats.st_mode & S_IFDIR) != 0) {
		/* directory */
		return VM_DIRECTORY;
	}
	ch = _tcsrchr( vm, _T_ECLIPSE('.') );
	if(ch == NULL)
		return VM_OTHER;
#ifdef _WIN32
	if (_tcsicmp(ch, _T_ECLIPSE(".dll")) == 0)
#else
	if ((_tcsicmp(ch, _T_ECLIPSE(".so")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".jnilib")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".dylib")) == 0))
#endif
	{
		return VM_LIBRARY;
	}
	if (_tcsicmp(ch, _T_ECLIPSE(".ee")) == 0)
		return VM_EE_PROPS;
	return VM_OTHER;
}
/*
* pathList is a pathSeparator separated list of paths, run each through
* checkPath and recombine the results.
* New memory is always allocated for the result
*/
_TCHAR * checkPathList( _TCHAR* pathList, _TCHAR* programDir, int reverseOrder) {
	_TCHAR * c1, *c2;
	_TCHAR * checked, *result;
	size_t checkedLength = 0, resultLength = 0;
	size_t bufferLength = _tcslen(pathList);
	result = malloc(bufferLength * sizeof(_TCHAR));
	c1 = pathList;
  while (c1 != NULL && *c1 != _T_ECLIPSE('\0'))
  {
  	c2 = _tcschr(c1, pathSeparator);
		if (c2 != NULL)
			*c2 = 0;
		checked = checkPath(c1, programDir, reverseOrder);
		checkedLength = _tcslen(checked);
		if (resultLength + checkedLength + 1> bufferLength) {
			bufferLength += checkedLength + 1;
			result = realloc(result, bufferLength * sizeof(_TCHAR));
		}
		if(resultLength > 0) {
			result[resultLength++] = pathSeparator;
			result[resultLength] = _T_ECLIPSE('\0');
		}
		_tcscpy(result + resultLength, checked);
		resultLength += checkedLength;
		if(checked != c1)
			free(checked);
		if(c2 != NULL)
			*(c2++) = pathSeparator;
		c1 = c2;
	}
  return result;
}
_TCHAR * concatStrings(_TCHAR**strs) {
	return concatPaths(strs, 0);
}
_TCHAR * concatPaths(_TCHAR** strs, _TCHAR separator) {
	_TCHAR separatorString[] = { separator, 0 };
	_TCHAR * result;
	int i = -1;
	size_t length = 0;
	/* first count how large a buffer we need */
	while (strs[++i] != NULL) {
		length += _tcslen(strs[i]) + (separator != 0 ? 1 : 0);
	}
	result = malloc((length + 1) * sizeof(_TCHAR));
	result[0] = 0;
	i = -1;
	while (strs[++i] != NULL) {
		result = _tcscat(result, strs[i]);
		if (separator != 0)
			result = _tcscat(result, separatorString);
	}
	return result;
}
/*
* buffer contains a pathSeparator separated list of paths, check 
* that it contains all the paths given.  Each path is expected to be
* terminated with a pathSeparator character.
*/
int containsPaths(_TCHAR * str, _TCHAR** paths) {
	_TCHAR * buffer;
	_TCHAR * c;
	int i;
	/* terminate the string with a pathSeparator */
	buffer = malloc((_tcslen(str) + 2) * sizeof(_TCHAR));
	_stprintf(buffer, _T_ECLIPSE("%s%c"), str, pathSeparator);
	for (i = 0; paths[i] != NULL; i++) {
		c = _tcsstr(buffer, paths[i]);
		if ( c == NULL || !(c == buffer || *(c - 1) == pathSeparator))
		{
			/* entry not found */
			free(buffer);
			return 0;
		}
	}
	free(buffer);
	return 1;
}
int isVMLibrary( _TCHAR* vm )
{
	_TCHAR *ch = NULL;
	if (vm == NULL) return 0;
	ch = _tcsrchr( vm, '.' );
	if(ch == NULL)
		return 0;
#ifdef _WIN32
	return (_tcsicmp(ch, _T_ECLIPSE(".dll")) == 0);
#else
	return (_tcsicmp(ch, _T_ECLIPSE(".so")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".jnilib")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".dylib")) == 0);
#endif
}
#ifdef AIX
#include <sys/types.h>
#include <time.h>
/* Return the JVM version in the format x.x.x 
*/
char* getVMVersion( char *vmPath )
{
  char   cmd[MAX_LINE_LENGTH];
  char   lineString[MAX_LINE_LENGTH];
  char*  firstChar;
  char   fileName[MAX_LINE_LENGTH];
  time_t curTime;
  FILE*  fp;
  int    numChars = 0;
  char*  version  = NULL;
	/* Define a unique filename for the java output. */
  (void) time(&curTime);
  (void) sprintf(fileName, "/tmp/tmp%ld.txt", curTime);
  /* Write java -version output to a temp file */
  (void) sprintf(cmd,"%s -version 2> %s", vmPath, fileName);
  (void) system(cmd); 
  fp = fopen(fileName, "r");
  if (fp != NULL)
  {
  	/* Read java -version output from a temp file */
  	if (fgets(lineString, MAX_LINE_LENGTH, fp) == NULL)
  		lineString[0] = '\0';
  	fclose(fp);
  	unlink(fileName);
  	/* Extract version number */
  	firstChar = (char *) (strchr(lineString, '"') + 1);
  	if (firstChar != NULL)
  		numChars = (int)  (strrchr(lineString, '"') - firstChar);
  	/* Allocate a buffer and copy the version string into it. */
  	if (numChars > 0)
  	{
  		version = malloc( numChars + 1 );
  		strncpy(version, firstChar, numChars);
			version[numChars] = '\0';
		}
	}  
  return version;
}
/* Compare JVM Versions of the form "x.x.x..."
*     
*    Returns -1 if ver1 < ver2
*    Returns  0 if ver1 = ver2 
*    Returns  1 if ver1 > ver2
*/     
int versionCmp(char *ver1, char *ver2)
{
  char*  dot1;
  char*  dot2;
  int    num1;
  int    num2;
  dot1 = strchr(ver1, '.');
  dot2 = strchr(ver2, '.');
  num1 = atoi(ver1);
  num2 = atoi(ver2);
  if (num1 > num2)
  	return 1;
	if (num1 < num2)
		return -1;
	if (dot1 && !dot2)   /* x.y > x */
      return 1;
  if (!dot1 && dot2)   /* x < x.y */
      return -1;
  if (!dot1 && !dot2)  /* x == x */
      return 0;
  return versionCmp((char*)(dot1 + 1), (char*)(dot2 + 1) );
}
#endif /* AIX */

 

二、总结

  • C 语言的学习需要勤思考勤动手才能得到
  • 提高难点部分为指针的学习
  • 指针的本质,指针的运算,指针和数组
  • 学习过程可以采用各个击破的方法
  • 在一个特定的时间段只重点学习和练习某个主题
  • 在熟练掌握C语言的各个特性后再进行项目练习

至此,C 语言进阶剖析学完,完结撒花。

但是,以后路还很远,还需要多加总结,才能真正掌握 C 语言。

到此这篇关于C语言容易被忽视的函数设计原则基础的文章就介绍到这了,更多相关C语言函数设计原则内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_43129713/article/details/124165352

延伸 · 阅读

精彩推荐
  • C/C++C++实现图书馆管理系统源码

    C++实现图书馆管理系统源码

    这篇文章主要为大家详细介绍了C++实现图书馆管理系统源码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Complicated32111812022-10-18
  • C/C++C语言实现分治法实例

    C语言实现分治法实例

    这篇文章主要为大家详细介绍了C语言实现分治法的实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    我站在桥上看风景3752021-07-01
  • C/C++C++ LARGE_INTEGER解析与使用案例详解

    C++ LARGE_INTEGER解析与使用案例详解

    这篇文章主要介绍了C++ LARGE_INTEGER解析与使用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    零点零一11282021-12-24
  • C/C++C/C++多参数函数参数的计算顺序与压栈顺序的示例代码

    C/C++多参数函数参数的计算顺序与压栈顺序的示例代码

    这篇文章主要介绍了C/C++多参数函数参数的计算顺序与压栈顺序,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,...

    _程序兔6242021-09-09
  • C/C++详解如何用alpine镜像做一个最小的镜像并运行c++程序

    详解如何用alpine镜像做一个最小的镜像并运行c++程序

    这篇文章主要介绍了详解如何用alpine镜像做一个最小的镜像并运行c++程序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习...

    Coldestmonth7602021-09-29
  • C/C++C语言switch语句详解

    C语言switch语句详解

    这篇文章主要为大家介绍了C语言switch语句,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助...

    Alienware^8622022-07-19
  • C/C++c语言网络编程-标准步骤(比较简单)

    c语言网络编程-标准步骤(比较简单)

    这篇文章主要介绍了c语言网络编程-标准步骤(比较简单),需要的朋友可以参考下...

    C语言程序设计8692021-01-14
  • C/C++关于C++运算符重载的一些困惑详解

    关于C++运算符重载的一些困惑详解

    这篇文章主要给大家介绍了关于C++运算符重载的一些困惑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    bruce62811442021-11-02